Add codegen for entrypoint method & fixes
This commit is contained in:
parent
fcf65eb627
commit
1b48c14a83
5 changed files with 474 additions and 7 deletions
|
@ -4,7 +4,19 @@ public class CodegenImpl implements Codegen {
|
|||
public CodegenImpl() {}
|
||||
|
||||
public String codegen(Program p) throws CodegenException {
|
||||
return "";
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Declaration main = null;
|
||||
|
||||
for (Declaration d : p.decls) {
|
||||
if (main == null) {
|
||||
main = d;
|
||||
}
|
||||
|
||||
builder.append(compileDeclaration(d));
|
||||
}
|
||||
|
||||
return builder.toString()
|
||||
+ "call " + String.format("%s_%d:\n", main.id, main.numOfArgs);
|
||||
}
|
||||
|
||||
private String generateLabel() {
|
||||
|
@ -88,15 +100,16 @@ public class CodegenImpl implements Codegen {
|
|||
String compLabel = generateLabel();
|
||||
String bodyLabel = generateLabel();
|
||||
String exitLabel = generateLabel();
|
||||
String contLabel = generateLabel();
|
||||
String breakLabel = generateLabel();
|
||||
|
||||
return "sw s2,-8(sp)\n"
|
||||
+ "sw s3,-4(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "la s2," + bodyLabel + "\n" // TODO: does this jump to the check?
|
||||
+ "la s2," + contLabel + "\n"
|
||||
+ "la s3," + breakLabel + "\n"
|
||||
+ bodyLabel + ": " + compileExp(eUntil.body)
|
||||
+ "sw s4,-4(sp)\n"
|
||||
+ contLabel + ": sw s4,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s4,a0\n"
|
||||
+ compileFullComp(eUntil.l, eUntil.r, eUntil.comp, exitLabel, compLabel)
|
||||
|
@ -136,7 +149,7 @@ public class CodegenImpl implements Codegen {
|
|||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// Store return address & current stack pointer
|
||||
builder.append("mv s3,sp\n");
|
||||
builder.append("mv s7,sp\n");
|
||||
builder.append("sw ra,-4(sp)\n");
|
||||
builder.append("addi sp,sp,-4\n");
|
||||
|
||||
|
@ -152,7 +165,7 @@ public class CodegenImpl implements Codegen {
|
|||
|
||||
// push old frame pointer & start-of-frame pointer
|
||||
builder.append("sw fp,-4(sp)\n");
|
||||
builder.append("sw s3,-8(sp)\n");
|
||||
builder.append("sw s7,-8(sp)\n");
|
||||
builder.append("addi sp,sp,-8\n");
|
||||
|
||||
builder.append(
|
||||
|
|
227
task2/CodegenImpl.java
Normal file
227
task2/CodegenImpl.java
Normal file
|
@ -0,0 +1,227 @@
|
|||
public class CodegenImpl implements Codegen {
|
||||
private int labelCounter = 0;
|
||||
|
||||
public CodegenImpl() {}
|
||||
|
||||
public String codegen(Program p) throws CodegenException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Declaration main = null;
|
||||
|
||||
for (Declaration d : p.decls) {
|
||||
if (main == null) {
|
||||
main = d;
|
||||
}
|
||||
|
||||
builder.append(compileDeclaration(d));
|
||||
}
|
||||
|
||||
return builder.toString()
|
||||
+ "call " + String.format("%s_%d:\n", main.id, main.numOfArgs);
|
||||
}
|
||||
|
||||
private String generateLabel() {
|
||||
return String.format("branch_%d", labelCounter++);
|
||||
}
|
||||
|
||||
public String compileDeclaration(Declaration d) throws CodegenException {
|
||||
return String.format("%s_%d:\n", d.id, d.numOfArgs)
|
||||
+ compileExp(d.body)
|
||||
+ "ret\n";
|
||||
}
|
||||
|
||||
public String compileExp(Exp e) throws CodegenException {
|
||||
if (e instanceof IntLiteral) {
|
||||
return String.format("li a0,%d\n", ((IntLiteral) e).n);
|
||||
} else if (e instanceof If) {
|
||||
If eIf = (If) e;
|
||||
|
||||
String thenLabel = generateLabel();
|
||||
String elseLabel = generateLabel();
|
||||
String finalizeLabel = generateLabel();
|
||||
|
||||
return compileFullComp(eIf.l, eIf.r, eIf.comp, thenLabel, elseLabel)
|
||||
+ thenLabel + ": " + compileExp(eIf.thenBody)
|
||||
+ "j " + finalizeLabel + "\n"
|
||||
+ elseLabel + ": " + compileExp(eIf.elseBody)
|
||||
+ finalizeLabel + ": " + "lw s1,(sp)\n"
|
||||
+ "addi sp,sp,4\n";
|
||||
} else if (e instanceof Binexp) {
|
||||
Binexp b = (Binexp) e;
|
||||
|
||||
return compileExp(b.l)
|
||||
+ "sw s1,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s1,a0\n"
|
||||
+ compileExp(b.r)
|
||||
+ "mv t1,a0\n"
|
||||
+ compileExpBinop(b.binop);
|
||||
} else if (e instanceof Variable) {
|
||||
int offset = ((Variable) e).x;
|
||||
|
||||
return String.format("lw a0,%d(fp)\n", offset * 4);
|
||||
} else if (e instanceof Invoke) {
|
||||
return compileCall((Invoke) e, false);
|
||||
} else if (e instanceof Seq) {
|
||||
String result = "";
|
||||
Seq statements = (Seq) e;
|
||||
|
||||
if (statements.r instanceof Invoke) {
|
||||
// tail call
|
||||
result = compileCall((Invoke) statements.r, true);
|
||||
} else {
|
||||
result = compileExp(statements.r);
|
||||
}
|
||||
|
||||
return compileExp(statements.l) + result;
|
||||
} else if (e instanceof While) {
|
||||
While eWhile = (While) e;
|
||||
|
||||
String startLabel = generateLabel();
|
||||
String bodyLabel = generateLabel();
|
||||
String exitLabel = generateLabel();
|
||||
|
||||
return "sw s2,-4(sp)\n"
|
||||
+ "sw s3,-8(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "la s2," + startLabel + "\n"
|
||||
+ "la s3," + exitLabel + "\n"
|
||||
+ startLabel + ": " + compileFullComp(eWhile.l, eWhile.r, eWhile.comp, bodyLabel, exitLabel)
|
||||
+ bodyLabel + ": " + compileExp(eWhile.body)
|
||||
+ "lw s1,(sp)\n"
|
||||
+ "addi sp,sp,4\n"
|
||||
+ "j " + startLabel + "\n"
|
||||
+ exitLabel + ": lw s1,(sp)\n"
|
||||
+ "lw s3,4(sp)\n"
|
||||
+ "lw s2,8(sp)\n"
|
||||
+ "addi sp,sp,12\n";
|
||||
} else if (e instanceof RepeatUntil) {
|
||||
RepeatUntil eUntil = (RepeatUntil) e;
|
||||
|
||||
String compLabel = generateLabel();
|
||||
String bodyLabel = generateLabel();
|
||||
String exitLabel = generateLabel();
|
||||
String contLabel = generateLabel();
|
||||
String breakLabel = generateLabel();
|
||||
|
||||
return "sw s2,-8(sp)\n"
|
||||
+ "sw s3,-4(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "la s2," + contLabel + "\n"
|
||||
+ "la s3," + breakLabel + "\n"
|
||||
+ bodyLabel + ": " + compileExp(eUntil.body)
|
||||
+ contLabel + ": sw s4,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s4,a0\n"
|
||||
+ compileFullComp(eUntil.l, eUntil.r, eUntil.comp, exitLabel, compLabel)
|
||||
+ compLabel + ": lw s1,(sp)\n"
|
||||
+ "lw s4,4(sp)\n"
|
||||
+ "addi sp,sp,8\n"
|
||||
+ "j " + bodyLabel + "\n"
|
||||
+ breakLabel + ": sw s1,-8(sp)\n"
|
||||
+ "sw s4,-4(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "mv s4,a0\n"
|
||||
+ exitLabel + ": lw s1,(sp)\n"
|
||||
+ "mv a0,s4\n" // body result to accumulator
|
||||
+ "lw s4,4(sp)\n" // restore previous s4
|
||||
+ "lw s2,8(sp)\n"
|
||||
+ "lw s3,12(sp)\n"
|
||||
+ "addi sp,sp,16\n";
|
||||
} else if (e instanceof Assign) {
|
||||
Assign assign = (Assign) e;
|
||||
|
||||
return compileExp(assign.e)
|
||||
+ String.format("sw a0,%d(fp)", assign.x * 4);
|
||||
} else if (e instanceof Continue) {
|
||||
return "jr s2\n";
|
||||
} else if (e instanceof Break) {
|
||||
return "jr s3\n";
|
||||
} else if (e instanceof Skip) {
|
||||
return "nop\n";
|
||||
}
|
||||
|
||||
throw new CodegenException("Unsupported expression!");
|
||||
}
|
||||
|
||||
public String compileCall(Invoke call, boolean tailCall) throws CodegenException {
|
||||
int argLen = call.args.size();
|
||||
String methodLabel = String.format("%s_%d", call.name, argLen);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// Store return address & current stack pointer
|
||||
builder.append("mv s7,sp\n");
|
||||
builder.append("sw ra,-4(sp)\n");
|
||||
builder.append("addi sp,sp,-4\n");
|
||||
|
||||
for (int i = argLen - 1; i >= 0; i--) {
|
||||
Exp argExp = call.args.get(i);
|
||||
|
||||
builder.append(compileExp(argExp));
|
||||
builder.append(
|
||||
"sw a0,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
);
|
||||
}
|
||||
|
||||
// push old frame pointer & start-of-frame pointer
|
||||
builder.append("sw fp,-4(sp)\n");
|
||||
builder.append("sw s7,-8(sp)\n");
|
||||
builder.append("addi sp,sp,-8\n");
|
||||
|
||||
builder.append(
|
||||
// set frame pointer to start of arguments
|
||||
"addi fp,sp,8\n"
|
||||
+ "call " + methodLabel + "\n"
|
||||
// restore old frame pointer & stack pointer
|
||||
+ "lw fp,4(sp)\n"
|
||||
+ "lw sp,(sp)\n"
|
||||
+ "lw ra,-4(sp)\n"
|
||||
);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String compileFullComp(Exp left, Exp right, Comp c, String successLabel, String failLabel) throws CodegenException {
|
||||
return compileExp(left)
|
||||
+ "sw s1,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s1,a0\n"
|
||||
+ compileExp(right)
|
||||
+ "mv t1,a0\n"
|
||||
+ compileComp(c, successLabel, failLabel);
|
||||
}
|
||||
|
||||
public String compileComp(Comp c, String thenLabel, String elseLabel) throws CodegenException {
|
||||
String instruction = "";
|
||||
|
||||
if (c instanceof Equals) {
|
||||
instruction = "beq";
|
||||
} else if (c instanceof Less) {
|
||||
instruction = "blt";
|
||||
} else if (c instanceof LessEq) {
|
||||
instruction = "ble";
|
||||
} else if (c instanceof Greater) {
|
||||
instruction = "bgt";
|
||||
} else if (c instanceof GreaterEq) {
|
||||
instruction = "bge";
|
||||
} else {
|
||||
throw new CodegenException("Unsupported comparison!");
|
||||
}
|
||||
|
||||
return String.format("%s s1,t1,%s\nb %s\n", instruction, thenLabel, elseLabel);
|
||||
}
|
||||
|
||||
public String compileExpBinop(Binop bin) throws CodegenException {
|
||||
if (bin instanceof Plus) {
|
||||
return "add a0,s1,t1\n";
|
||||
} else if (bin instanceof Minus) {
|
||||
return "sub a0,s1,t1\n";
|
||||
} else if (bin instanceof Times) {
|
||||
return "mul a0,s1,t1\n";
|
||||
} else if (bin instanceof Div) {
|
||||
return "div a0,s1,t1\n";
|
||||
}
|
||||
|
||||
throw new CodegenException("Unsupported bin-op! " + bin);
|
||||
}
|
||||
}
|
|
@ -6,4 +6,4 @@
|
|||
// welcome to add new classes! Please put them into separate files.
|
||||
|
||||
class Task2 {
|
||||
public static Codegen create () throws CodegenException { ... } }
|
||||
public static Codegen create () throws CodegenException { return new CodegenImpl(); } }
|
||||
|
|
227
task3/CodegenImpl.java
Normal file
227
task3/CodegenImpl.java
Normal file
|
@ -0,0 +1,227 @@
|
|||
public class CodegenImpl implements Codegen {
|
||||
private int labelCounter = 0;
|
||||
|
||||
public CodegenImpl() {}
|
||||
|
||||
public String codegen(Program p) throws CodegenException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
Declaration main = null;
|
||||
|
||||
for (Declaration d : p.decls) {
|
||||
if (main == null) {
|
||||
main = d;
|
||||
}
|
||||
|
||||
builder.append(compileDeclaration(d));
|
||||
}
|
||||
|
||||
return builder.toString()
|
||||
+ "call " + String.format("%s_%d:\n", main.id, main.numOfArgs);
|
||||
}
|
||||
|
||||
private String generateLabel() {
|
||||
return String.format("branch_%d", labelCounter++);
|
||||
}
|
||||
|
||||
public String compileDeclaration(Declaration d) throws CodegenException {
|
||||
return String.format("%s_%d:\n", d.id, d.numOfArgs)
|
||||
+ compileExp(d.body)
|
||||
+ "ret\n";
|
||||
}
|
||||
|
||||
public String compileExp(Exp e) throws CodegenException {
|
||||
if (e instanceof IntLiteral) {
|
||||
return String.format("li a0,%d\n", ((IntLiteral) e).n);
|
||||
} else if (e instanceof If) {
|
||||
If eIf = (If) e;
|
||||
|
||||
String thenLabel = generateLabel();
|
||||
String elseLabel = generateLabel();
|
||||
String finalizeLabel = generateLabel();
|
||||
|
||||
return compileFullComp(eIf.l, eIf.r, eIf.comp, thenLabel, elseLabel)
|
||||
+ thenLabel + ": " + compileExp(eIf.thenBody)
|
||||
+ "j " + finalizeLabel + "\n"
|
||||
+ elseLabel + ": " + compileExp(eIf.elseBody)
|
||||
+ finalizeLabel + ": " + "lw s1,(sp)\n"
|
||||
+ "addi sp,sp,4\n";
|
||||
} else if (e instanceof Binexp) {
|
||||
Binexp b = (Binexp) e;
|
||||
|
||||
return compileExp(b.l)
|
||||
+ "sw s1,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s1,a0\n"
|
||||
+ compileExp(b.r)
|
||||
+ "mv t1,a0\n"
|
||||
+ compileExpBinop(b.binop);
|
||||
} else if (e instanceof Variable) {
|
||||
int offset = ((Variable) e).x;
|
||||
|
||||
return String.format("lw a0,%d(fp)\n", offset * 4);
|
||||
} else if (e instanceof Invoke) {
|
||||
return compileCall((Invoke) e, false);
|
||||
} else if (e instanceof Seq) {
|
||||
String result = "";
|
||||
Seq statements = (Seq) e;
|
||||
|
||||
if (statements.r instanceof Invoke) {
|
||||
// tail call
|
||||
result = compileCall((Invoke) statements.r, true);
|
||||
} else {
|
||||
result = compileExp(statements.r);
|
||||
}
|
||||
|
||||
return compileExp(statements.l) + result;
|
||||
} else if (e instanceof While) {
|
||||
While eWhile = (While) e;
|
||||
|
||||
String startLabel = generateLabel();
|
||||
String bodyLabel = generateLabel();
|
||||
String exitLabel = generateLabel();
|
||||
|
||||
return "sw s2,-4(sp)\n"
|
||||
+ "sw s3,-8(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "la s2," + startLabel + "\n"
|
||||
+ "la s3," + exitLabel + "\n"
|
||||
+ startLabel + ": " + compileFullComp(eWhile.l, eWhile.r, eWhile.comp, bodyLabel, exitLabel)
|
||||
+ bodyLabel + ": " + compileExp(eWhile.body)
|
||||
+ "lw s1,(sp)\n"
|
||||
+ "addi sp,sp,4\n"
|
||||
+ "j " + startLabel + "\n"
|
||||
+ exitLabel + ": lw s1,(sp)\n"
|
||||
+ "lw s3,4(sp)\n"
|
||||
+ "lw s2,8(sp)\n"
|
||||
+ "addi sp,sp,12\n";
|
||||
} else if (e instanceof RepeatUntil) {
|
||||
RepeatUntil eUntil = (RepeatUntil) e;
|
||||
|
||||
String compLabel = generateLabel();
|
||||
String bodyLabel = generateLabel();
|
||||
String exitLabel = generateLabel();
|
||||
String contLabel = generateLabel();
|
||||
String breakLabel = generateLabel();
|
||||
|
||||
return "sw s2,-8(sp)\n"
|
||||
+ "sw s3,-4(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "la s2," + contLabel + "\n"
|
||||
+ "la s3," + breakLabel + "\n"
|
||||
+ bodyLabel + ": " + compileExp(eUntil.body)
|
||||
+ contLabel + ": sw s4,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s4,a0\n"
|
||||
+ compileFullComp(eUntil.l, eUntil.r, eUntil.comp, exitLabel, compLabel)
|
||||
+ compLabel + ": lw s1,(sp)\n"
|
||||
+ "lw s4,4(sp)\n"
|
||||
+ "addi sp,sp,8\n"
|
||||
+ "j " + bodyLabel + "\n"
|
||||
+ breakLabel + ": sw s1,-8(sp)\n"
|
||||
+ "sw s4,-4(sp)\n"
|
||||
+ "addi sp,sp,-8\n"
|
||||
+ "mv s4,a0\n"
|
||||
+ exitLabel + ": lw s1,(sp)\n"
|
||||
+ "mv a0,s4\n" // body result to accumulator
|
||||
+ "lw s4,4(sp)\n" // restore previous s4
|
||||
+ "lw s2,8(sp)\n"
|
||||
+ "lw s3,12(sp)\n"
|
||||
+ "addi sp,sp,16\n";
|
||||
} else if (e instanceof Assign) {
|
||||
Assign assign = (Assign) e;
|
||||
|
||||
return compileExp(assign.e)
|
||||
+ String.format("sw a0,%d(fp)", assign.x * 4);
|
||||
} else if (e instanceof Continue) {
|
||||
return "jr s2\n";
|
||||
} else if (e instanceof Break) {
|
||||
return "jr s3\n";
|
||||
} else if (e instanceof Skip) {
|
||||
return "nop\n";
|
||||
}
|
||||
|
||||
throw new CodegenException("Unsupported expression!");
|
||||
}
|
||||
|
||||
public String compileCall(Invoke call, boolean tailCall) throws CodegenException {
|
||||
int argLen = call.args.size();
|
||||
String methodLabel = String.format("%s_%d", call.name, argLen);
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
// Store return address & current stack pointer
|
||||
builder.append("mv s7,sp\n");
|
||||
builder.append("sw ra,-4(sp)\n");
|
||||
builder.append("addi sp,sp,-4\n");
|
||||
|
||||
for (int i = argLen - 1; i >= 0; i--) {
|
||||
Exp argExp = call.args.get(i);
|
||||
|
||||
builder.append(compileExp(argExp));
|
||||
builder.append(
|
||||
"sw a0,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
);
|
||||
}
|
||||
|
||||
// push old frame pointer & start-of-frame pointer
|
||||
builder.append("sw fp,-4(sp)\n");
|
||||
builder.append("sw s7,-8(sp)\n");
|
||||
builder.append("addi sp,sp,-8\n");
|
||||
|
||||
builder.append(
|
||||
// set frame pointer to start of arguments
|
||||
"addi fp,sp,8\n"
|
||||
+ "call " + methodLabel + "\n"
|
||||
// restore old frame pointer & stack pointer
|
||||
+ "lw fp,4(sp)\n"
|
||||
+ "lw sp,(sp)\n"
|
||||
+ "lw ra,-4(sp)\n"
|
||||
);
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String compileFullComp(Exp left, Exp right, Comp c, String successLabel, String failLabel) throws CodegenException {
|
||||
return compileExp(left)
|
||||
+ "sw s1,-4(sp)\n"
|
||||
+ "addi sp,sp,-4\n"
|
||||
+ "mv s1,a0\n"
|
||||
+ compileExp(right)
|
||||
+ "mv t1,a0\n"
|
||||
+ compileComp(c, successLabel, failLabel);
|
||||
}
|
||||
|
||||
public String compileComp(Comp c, String thenLabel, String elseLabel) throws CodegenException {
|
||||
String instruction = "";
|
||||
|
||||
if (c instanceof Equals) {
|
||||
instruction = "beq";
|
||||
} else if (c instanceof Less) {
|
||||
instruction = "blt";
|
||||
} else if (c instanceof LessEq) {
|
||||
instruction = "ble";
|
||||
} else if (c instanceof Greater) {
|
||||
instruction = "bgt";
|
||||
} else if (c instanceof GreaterEq) {
|
||||
instruction = "bge";
|
||||
} else {
|
||||
throw new CodegenException("Unsupported comparison!");
|
||||
}
|
||||
|
||||
return String.format("%s s1,t1,%s\nb %s\n", instruction, thenLabel, elseLabel);
|
||||
}
|
||||
|
||||
public String compileExpBinop(Binop bin) throws CodegenException {
|
||||
if (bin instanceof Plus) {
|
||||
return "add a0,s1,t1\n";
|
||||
} else if (bin instanceof Minus) {
|
||||
return "sub a0,s1,t1\n";
|
||||
} else if (bin instanceof Times) {
|
||||
return "mul a0,s1,t1\n";
|
||||
} else if (bin instanceof Div) {
|
||||
return "div a0,s1,t1\n";
|
||||
}
|
||||
|
||||
throw new CodegenException("Unsupported bin-op! " + bin);
|
||||
}
|
||||
}
|
|
@ -6,4 +6,4 @@
|
|||
// welcome to add new classes! Please put them into separate files.
|
||||
|
||||
class Task3 {
|
||||
public static Codegen create () throws CodegenException { ... } }
|
||||
public static Codegen create () throws CodegenException { return new CodegenImpl(); } }
|
||||
|
|
Loading…
Reference in a new issue