プロジェクトの完全なコードC2j、コンパイラ
序文
上のJVMの命令の生成を完了するには、実際にコード生成の次のセクションを入力することができます。現代のコンパイラは通常、第一世代のIR、その後、コードの最適化を通じてというように、そして最終的にターゲットプラットフォーム用のコードにコンパイルされています。しかし、限られた時間のレベルは、我々はIRコード最適化しませんでした、直接Javaが生成されたASTを使用してバイトコード
エントランス
コードは、コード生成の入口に生成され、前に説明したのと同様である:ヘッドノードの主な機能を得るために、最初の関数に先頭からノードは、定義され、そして、コードブロックを入力されています
関数定義ノード
ノード関数定義を入力する場合、我々が全体のクラスのためのC言語ファイル、主要公共、主静的他人のための方法として生成対応しているので(Javaバイトコードで定義された対応する機能、すなわち、静的メソッドを生成する必要があります静的メソッドは、構造体)は、別のクラスであります
- 開始ノードと、対応する機能コマンドパラメータを取得するための関数の定義
- emitArgs処理パラメータがパラメータに従って対応するJavaバイトコードを生成するために使用されます
- この機能は、メインである場合には(start.Startで特に)ほぼロジック、前処理に引き渡されてい
case SyntaxProductionInit.NewName_LP_RP_TO_FunctDecl:
root.reverseChildren();
AstNode n = root.getChildren().get(0);
String name = (String) n.getAttribute(NodeKey.TEXT);
symbol = (Symbol) root.getAttribute(NodeKey.SYMBOL);
generator.setCurrentFuncName(name);
if (name != null && !name.equals("main")) {
String declaration = name + emitArgs(symbol);
generator.emitDirective(Directive.METHOD_PUBBLIC_STATIC, declaration);
generator.setNameAndDeclaration(name, declaration);
}
copyChild(root, root.getChildren().get(0));
break;
case SyntaxProductionInit.NewName_LP_VarList_RP_TO_FunctDecl:
n = root.getChildren().get(0);
name = (String) n.getAttribute(NodeKey.TEXT);
symbol = (Symbol) root.getAttribute(NodeKey.SYMBOL);
generator.setCurrentFuncName(name);
if (name != null && !name.equals("main")) {
String declaration = name + emitArgs(symbol);
generator.emitDirective(Directive.METHOD_PUBBLIC_STATIC, declaration);
generator.setNameAndDeclaration(name, declaration);
}
Symbol args = symbol.getArgList();
if (args == null || argsList == null || argsList.isEmpty()) {
System.err.println("generate function with arg list but arg list is null");
System.exit(1);
}
break;
構造と配列を作成します
配列
ノードはDefGenerate内の構造と配列を作成し、あなたはそれが最初の使用時に構造体の構造を扱っている、通常の変数や配列を扱うここで見ることができます。なお、初期値のためのコード生成操作は処理されません。
- それが配列の場合、ワインは直接ProgramGeneratorが直接コマンドの配列を作成して生成された呼び出し
- それに直接割り当てられた通常の変数は、0(変数記号表に従って計算されるキュー内の位置、getLocalVariableIndexの具体的空想方式)である場合
public class DefGenerate extends BaseGenerate {
@Override
public Object generate(AstNode root) {
int production = (int) root.getAttribute(NodeKey.PRODUCTION);
ProgramGenerator generator = ProgramGenerator.getInstance();
Symbol symbol = (Symbol) root.getAttribute(NodeKey.SYMBOL);
switch (production) {
case SyntaxProductionInit.Specifiers_DeclList_Semi_TO_Def:
Declarator declarator = symbol.getDeclarator(Declarator.ARRAY);
if (declarator != null) {
if (symbol.getSpecifierByType(Specifier.STRUCTURE) == null) {
generator.createArray(symbol);
}
} else {
int i = generator.getLocalVariableIndex(symbol);
generator.emit(Instruction.SIPUSH, "" + 0);
generator.emit(Instruction.ISTORE, "" + i);
}
break;
default:
break;
}
return root;
}
}
構造
構造を定義するために使用される場合処理構造定義コードUnaryNodeGenerate、すなわちのみ定義されます
- ノートのinstanceofはArrayValueSetterがgetStructSymbolFromStructArrayに構造体の配列を作成する方法を入力して、構造体の配列で、被写体の下のオブジェクトの現在の構造を返した場合まず、現在のUNARYシンボルを取得します
- 現在のスコープ範囲の構造を設定します
- これは、クラスの構造として定義されています
- その後、ドメイン構造を読みます
- コード生成は、ポインタをシミュレートしていないため、実際には、ポインタ部分は、無視することができます
case SyntaxProductionInit.Unary_StructOP_Name_TO_Unary:
child = root.getChildren().get(0);
String fieldName = (String) root.getAttribute(NodeKey.TEXT);
Object object = child.getAttribute(NodeKey.SYMBOL);
boolean isStructArray = false;
if (object instanceof ArrayValueSetter) {
symbol = getStructSymbolFromStructArray(object);
symbol.addValueSetter(object);
isStructArray = true;
} else {
symbol = (Symbol) child.getAttribute(NodeKey.SYMBOL);
}
if (isStructArray) {
ArrayValueSetter vs = (ArrayValueSetter) object;
Symbol structArray = vs.getSymbol();
structArray.addScope(ProgramGenerator.getInstance().getCurrentFuncName());
} else {
symbol.addScope(ProgramGenerator.getInstance().getCurrentFuncName());
}
ProgramGenerator.getInstance().putStructToClassDeclaration(symbol);
if (isSymbolStructPointer(symbol)) {
copyBetweenStructAndMem(symbol, false);
}
Symbol args = symbol.getArgList();
while (args != null) {
if (args.getName().equals(fieldName)) {
args.setStructParent(symbol);
break;
}
args = args.getNextSymbol();
}
if (args == null) {
System.err.println("access a filed not in struct object!");
System.exit(1);
}
if (args.getValue() != null) {
ProgramGenerator.getInstance().readValueFromStructMember(symbol, args);
}
root.setAttribute(NodeKey.SYMBOL, args);
root.setAttribute(NodeKey.VALUE, args.getValue());
if (isSymbolStructPointer(symbol)) {
checkValidPointer(symbol);
structObjSymbol = symbol;
monitorSymbol = args;
GenerateBrocasterImpl.getInstance().registerReceiverForAfterExe(this);
} else {
structObjSymbol = null;
}
break;
単項演算子ノード
このノードには、同じ番号を持っており、インタプリタでは、構造体の操作に加えて、他にも非常に重要な役割であります
- 数値、文字列または変数および操作のような事前情報は、親ノードと呼ばれる親ノードのプロセスに送信されます
case SyntaxProductionInit.Number_TO_Unary:
text = (String) root.getAttribute(NodeKey.TEXT);
boolean isFloat = text.indexOf('.') != -1;
if (isFloat) {
value = Float.valueOf(text);
root.setAttribute(NodeKey.VALUE, value);
} else {
value = Integer.valueOf(text);
root.setAttribute(NodeKey.VALUE, value);
}
break;
case SyntaxProductionInit.Name_TO_Unary:
symbol = (Symbol) root.getAttribute(NodeKey.SYMBOL);
if (symbol != null) {
root.setAttribute(NodeKey.VALUE, symbol.getValue());
root.setAttribute(NodeKey.TEXT, symbol.getName());
}
break;
case SyntaxProductionInit.String_TO_Unary:
text = (String) root.getAttribute(NodeKey.TEXT);
root.setAttribute(NodeKey.VALUE, text);
break;
case SyntaxProductionInit.Unary_LB_Expr_RB_TO_Unary:
child = root.getChildren().get(0);
symbol = (Symbol) child.getAttribute(NodeKey.SYMBOL);
child = root.getChildren().get(1);
int index = 0;
if (child.getAttribute(NodeKey.VALUE) != null) {
index = (Integer) child.getAttribute(NodeKey.VALUE);
}
Object idxObj = child.getAttribute(NodeKey.SYMBOL);
try {
Declarator declarator = symbol.getDeclarator(Declarator.ARRAY);
if (declarator != null) {
Object val = declarator.getElement((int) index);
root.setAttribute(NodeKey.VALUE, val);
ArrayValueSetter setter;
if (idxObj == null) {
setter = new ArrayValueSetter(symbol, index);
} else {
setter = new ArrayValueSetter(symbol, idxObj);
}
root.setAttribute(NodeKey.SYMBOL, setter);
root.setAttribute(NodeKey.TEXT, symbol.getName());
}
Declarator pointer = symbol.getDeclarator(Declarator.POINTER);
if (pointer != null) {
setPointerValue(root, symbol, index);
PointerValueSetter pv = new PointerValueSetter(symbol, index);
root.setAttribute(NodeKey.SYMBOL, pv);
root.setAttribute(NodeKey.TEXT, symbol.getName());
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
break;
割り当て
- 電流が配列である場合は、最初にその記号と添字を取得
- それは構造体の配列でない場合は、配列要素を取得するための添字生成命令は、直接読み取るreadArrayElement
- 記号はgetLocalVariableIndexを読んで値を持つシンボルである場合
- それが一定であれば、直接命令を生成IPUSH
- それはドメイン構造を割り当てることではない場合getLocalVariableIndexは、キュー位置ISTOREを生成して最後に割り当て、直接になるだろう
- 割り当ては構造体の配列の要素をフィールドする場合、それはassignValueToStructMemberFromArrayコードを生成し呼び出しが、構造が直接生成される場合、コードはassignValueToStructMemberを呼び出し
ProgramGenerator generator = ProgramGenerator.getInstance();
if (BaseGenerate.resultOnStack) {
this.value = obj;
BaseGenerate.resultOnStack = false;
} else if (obj instanceof ArrayValueSetter) {
ArrayValueSetter setter = (ArrayValueSetter) obj;
Symbol symbol = setter.getSymbol();
Object index = setter.getIndex();
if (symbol.getSpecifierByType(Specifier.STRUCTURE) == null) {
if (index instanceof Symbol) {
ProgramGenerator.getInstance().readArrayElement(symbol, index);
if (((Symbol) index).getValue() != null) {
int i = (int) ((Symbol) index).getValue();
try {
this.value = symbol.getDeclarator(Declarator.ARRAY).getElement(i);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
int i = (int) index;
try {
this.value = symbol.getDeclarator(Declarator.ARRAY).getElement(i);
} catch (Exception e) {
e.printStackTrace();
}
ProgramGenerator.getInstance().readArrayElement(symbol, index);
}
}
} else if (obj instanceof Symbol) {
Symbol symbol = (Symbol) obj;
this.value = symbol.value;
int i = generator.getLocalVariableIndex(symbol);
generator.emit(Instruction.ILOAD, "" + i);
} else if (obj instanceof Integer) {
Integer val = (Integer) obj;
generator.emit(Instruction.SIPUSH, "" + val);
this.value = obj;
}
if (!this.isStructMember()) {
int idx = generator.getLocalVariableIndex(this);
if (!generator.isPassingArguments()) {
generator.emit(Instruction.ISTORE, "" + idx);
}
} else {
if (this.getStructSymbol().getValueSetter() != null) {
generator.assignValueToStructMemberFromArray(this.getStructSymbol().getValueSetter(), this, this.value);
} else {
generator.assignValueToStructMember(this.getStructSymbol(), this, this.value);
}
}
遂に
このセクションの終了後、次のコード
void quicksort(int A[10], int p, int r) {
int x;
int i;
i = p - 1;
int j;
int t;
int v;
v = r - 1;
if (p < r) {
x = A[r];
for (j = p; j <= v; j++) {
if (A[j] <= x) {
i++;
t = A[i];
A[i] = A[j];
A[j] = t;
}
}
v = i + 1;
t = A[v];
A[v] = A[r];
A[r] = t;
t = v - 1;
quicksort(A, p, t);
t = v + 1;
quicksort(A, t, r);
}
}
void main () {
int a[10];
int i;
int t;
printf("before quick sort:");
for(i = 0; i < 10; i++) {
t = (10 - i);
a[i] = t;
printf("value of a[%d] is %d", i, a[i]);
}
quicksort(a, 0, 9);
printf("after quick sort:");
for (i = 0; i < 10; i++) {
printf("value of a[%d] is %d", i, a[i]);
}
}
これは、Javaバイトコードの後に生成されます
.class public C2Bytecode
.super java/lang/Object
.method public static main([Ljava/lang/String;)V
sipush 10
newarray int
astore 0
sipush 0
istore 1
sipush 0
istore 2
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "before quick sort:"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "
"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
sipush 0
istore 1
loop0:
iload 1
sipush 10
if_icmpge branch0
sipush 10
iload 1
isub
istore 2
aload 0
iload 1
iload 2
iastore
aload 0
iload 1
iaload
istore 3
iload 1
istore 4
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "value of a["
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
iload 4
invokevirtual java/io/PrintStream/print(I)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "] is "
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
iload 3
invokevirtual java/io/PrintStream/print(I)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "
"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
iload 1
sipush 1
iadd
istore 1
goto loop0
branch0:
aload 0
sipush 0
sipush 9
invokestatic C2Bytecode/quicksort([III)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "after quick sort:"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "
"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
sipush 0
istore 1
loop2:
iload 1
sipush 10
if_icmpge branch4
aload 0
iload 1
iaload
istore 3
iload 1
istore 4
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "value of a["
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
iload 4
invokevirtual java/io/PrintStream/print(I)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "] is "
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
iload 3
invokevirtual java/io/PrintStream/print(I)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "
"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
iload 1
sipush 1
iadd
istore 1
goto loop2
branch4:
return
.end method
.method public static quicksort([III)V
sipush 2
newarray int
astore 6
sipush 0
istore 5
sipush 1
istore 5
aload 6
iload 5
sipush 1
iastore
aload 6
sipush 1
iaload
istore 10
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "before quick sort: "
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
getstatic java/lang/System/out Ljava/io/PrintStream;
iload 10
invokevirtual java/io/PrintStream/print(I)V
getstatic java/lang/System/out Ljava/io/PrintStream;
ldc "
"
invokevirtual java/io/PrintStream/print(Ljava/lang/String;)V
sipush 0
istore 9
sipush 0
istore 3
iload 1
sipush 1
isub
istore 3
sipush 0
istore 4
sipush 0
istore 7
sipush 0
istore 8
iload 2
sipush 1
isub
istore 8
iload 1
iload 2
if_icmpge branch1
aload 0
iload 2
iaload
istore 9
iload 1
istore 4
loop1:
iload 4
iload 8
if_icmpgt ibranch1
aload 0
iload 4
iaload
iload 9
if_icmpgt ibranch2
iload 3
sipush 1
iadd
istore 3
aload 0
iload 3
iaload
istore 7
aload 0
iload 3
aload 0
iload 4
iaload
iastore
aload 0
iload 4
iload 7
iastore
ibranch2:
iload 4
sipush 1
iadd
istore 4
goto loop1
ibranch1:
iload 3
sipush 1
iadd
istore 8
aload 0
iload 8
iaload
istore 7
aload 0
iload 8
aload 0
iload 2
iaload
iastore
aload 0
iload 2
iload 7
iastore
iload 8
sipush 1
isub
istore 7
aload 0
iload 1
iload 7
invokestatic C2Bytecode/quicksort([III)V
iload 8
sipush 1
iadd
istore 7
aload 0
iload 7
iload 2
invokestatic C2Bytecode/quicksort([III)V
branch1:
return
.end method
.end class
概要
このコード生成及びインタプリタが類似している前のアイデアが実行さASTまたはコード生成および対応する製造。
実際には、主要なアイデアは、人々があまりにも絡まあまりにも多くの詳細がありますが、非常に明確です。このシリーズはどの13があるし、私自身の研究ノートとして数え、次のものが正式に終了要約を書き込むことができます。
ようこそスター!