diff --git a/src/main/java/chocopy/pa3/CodeGenImpl.java b/src/main/java/chocopy/pa3/CodeGenImpl.java index 7d6c69f4b7d3c01a43b39c518efe97e5a2026c48..4d5fdcd194cc8f7b49370649fd66e5cfadb8358f 100644 --- a/src/main/java/chocopy/pa3/CodeGenImpl.java +++ b/src/main/java/chocopy/pa3/CodeGenImpl.java @@ -1,16 +1,14 @@ package chocopy.pa3; +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import chocopy.common.analysis.SymbolTable; import chocopy.common.analysis.AbstractNodeAnalyzer; -import chocopy.common.astnodes.Stmt; -import chocopy.common.astnodes.ReturnStmt; -import chocopy.common.codegen.CodeGenBase; -import chocopy.common.codegen.FuncInfo; -import chocopy.common.codegen.Label; -import chocopy.common.codegen.RiscVBackend; -import chocopy.common.codegen.SymbolInfo; +import chocopy.common.analysis.types.SymbolType; +import chocopy.common.astnodes.*; +import chocopy.common.codegen.*; import static chocopy.common.codegen.RiscVBackend.Register.*; @@ -60,7 +58,6 @@ public class CodeGenImpl extends CodeGenBase { backend.emitSW(ZERO, SP, 4, "Top saved RA is 0."); backend.emitADDI(FP, SP, 2 * backend.getWordSize(), "Set FP to previous SP."); - for (Stmt stmt : statements) { stmt.dispatch(stmtAnalyzer); } @@ -80,7 +77,13 @@ public class CodeGenImpl extends CodeGenBase { protected void emitUserDefinedFunction(FuncInfo funcInfo) { backend.emitGlobalLabel(funcInfo.getCodeLabel()); StmtAnalyzer stmtAnalyzer = new StmtAnalyzer(funcInfo); + // Prologue: + backend.emitSW(FP, SP, 0, "Save old FP"); + backend.emitSW(RA, SP, -4, "Save RA"); + backend.emitADDI(SP, SP, -8, "Increment stack pointer 2 places"); + backend.emitADDI(FP, SP, 4, "FP is one slot below top of stack"); + // Emit code for function stmts for (Stmt stmt : funcInfo.getStatements()) { stmt.dispatch(stmtAnalyzer); } @@ -89,11 +92,13 @@ public class CodeGenImpl extends CodeGenBase { backend.emitLocalLabel(stmtAnalyzer.epilogue, "Epilogue"); // FIXME: {... reset fp etc. ...} + backend.emitLW(RA, FP, 0, "Restore RA"); + backend.emitLW(FP, FP, 4, "Restore old FP"); backend.emitJR(RA, "Return to caller"); } /** An analyzer that encapsulates code generation for statments. */ - private class StmtAnalyzer extends AbstractNodeAnalyzer<Void> { + private class StmtAnalyzer extends AbstractNodeAnalyzer<Object> { /* * The symbol table has all the info you need to determine * what a given identifier 'x' in the current scope is. You can @@ -158,6 +163,97 @@ public class CodeGenImpl extends CodeGenBase { return null; } + @Override + public Void analyze(ExprStmt exprStmt) { + exprStmt.expr.dispatch(this); + return null; + } + + + @Override + public Void analyze(CallExpr callExpr) { + // NOT DONE + if (globalSymbols.get(callExpr.function.name) instanceof FuncInfo) { + FuncInfo func = (FuncInfo) globalSymbols.get(callExpr.function.name); + for (Expr e : callExpr.args) { + backend.emitADDI(SP, SP, -4, "Increment stack ptr by 1"); + e.dispatch(this); + } + // Push parameters onto stack + backend.emitJAL(func.getCodeLabel(), "Invoke function"); + + // Restore SP + for (Expr e : callExpr.args) { + backend.emitADDI(SP, SP, 4, "Increment stack ptr by 1"); + } + + } + return null; + } + + @Override + public Void analyze(BooleanLiteral literal) { + /* Push boolean literal onto stack, incrementing stack pointer*/ + backend.emitLA(A0, constants.getBoolConstant(literal.value), "Load boolean literal into a0"); + backend.emitSW(A0, SP, 0, "Push on stack"); + return null; + } + + @Override + public Void analyze(IntegerLiteral literal) { + backend.emitLA(A0, constants.getIntConstant(literal.value), "Load integer literal into a0"); + backend.emitSW(A0, SP, 0, "Push on stack"); + return null; + } + + @Override + public Void analyze(StringLiteral literal) { + backend.emitLA(A0, constants.getStrConstant(literal.value), "Load string literal into a0"); + backend.emitSW(A0, SP, 0, "Push on stack"); + return null; + } + + @Override + public Void analyze(Identifier id) { + // NOT DONE + SymbolInfo ident; + // global var case + if (this.funcInfo == null) { + ident = globalSymbols.get(id.name); + backend.emitLW(A0, ((GlobalVarInfo) ident).getLabel(), "Load identifier"); + backend.emitSW(A0, SP, 0, "Push to stack"); + } else { // local variable + ident = this.funcInfo.getSymbolTable().get(id.name); + } + return null; + } + + @Override + public Void analyze(BinaryExpr binaryExpr) { + switch (binaryExpr.operator) { + case "+": + // needs to be extended string concatenation, list concatenation + backend.emitADDI(SP, SP, -4, "Increment stack ptr for first operand"); + binaryExpr.left.dispatch(this); + backend.emitADDI(SP, SP, -4, "Increment stack ptr for second operand"); + binaryExpr.right.dispatch(this); + backend.emitLW(T0, SP, 0, "Load operand 2 into t0"); + backend.emitLW(T0, T0, "@.__int__", "Load value of operand 2 into t0"); + backend.emitADDI(SP, SP, 4, "Decrement stack ptr for first operand"); + backend.emitLW(T1, SP, 0, "Load operand 1 into t1"); + backend.emitLW(T1, T1, "@.__int__", "Load value of operand 1 into t1"); + backend.emitADDI(SP, SP, 4, "Decrement stack ptr for second operand"); + backend.emitADD(T0, T0, T1, "Add operands"); + backend.emitJAL(((FuncInfo) globalSymbols.get("int-alloc")).getCodeLabel(), "Jump to int alloc routine"); + backend.emitSW(T0, SP, 0, "Push result on stack"); + } + + return null; + } + @Override + public Void analyze(AssignStmt assignStmt) { + return null; + } // FIXME: More, of course. } @@ -186,6 +282,17 @@ public class CodeGenImpl extends CodeGenBase { * */ protected void emitCustomCode() { + backend.emitGlobalLabel(new Label("int-alloc")); + backend.emitLA(A0, intClass.getPrototypeLabel(), "Get int prototype address"); + backend.emitJAL(objectAllocLabel, "Allocate int"); + + FuncInfo allocInt = makeFuncInfo("int-alloc", 0, SymbolType.OBJECT_TYPE, + globalSymbols, null, this::emitStdFunc); + allocInt.addParam(makeStackVarInfo("arg", SymbolType.OBJECT_TYPE, + null, allocInt)); + functions.add(allocInt); + System.out.println(allocInt.getBaseName()); + globalSymbols.put(allocInt.getBaseName(), allocInt); emitErrorFunc(errorNone, "Operation on None"); emitErrorFunc(errorDiv, "Divison by zero"); emitErrorFunc(errorOob, "Index out of bounds");