Implement the entire code generator
This commit is contained in:
parent
ecbc9b750d
commit
fcf65eb627
2 changed files with 215 additions and 1 deletions
214
task1/CodegenImpl.java
Normal file
214
task1/CodegenImpl.java
Normal file
|
@ -0,0 +1,214 @@
|
||||||
|
public class CodegenImpl implements Codegen {
|
||||||
|
private int labelCounter = 0;
|
||||||
|
|
||||||
|
public CodegenImpl() {}
|
||||||
|
|
||||||
|
public String codegen(Program p) throws CodegenException {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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 s3," + breakLabel + "\n"
|
||||||
|
+ bodyLabel + ": " + compileExp(eUntil.body)
|
||||||
|
+ "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 s3,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 s3,-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.
|
// welcome to add new classes! Please put them into separate files.
|
||||||
|
|
||||||
class Task1 {
|
class Task1 {
|
||||||
public static Codegen create () throws CodegenException { ... } }
|
public static Codegen create () throws CodegenException { return new CodegenImpl(); } }
|
||||||
|
|
Loading…
Reference in a new issue