From 5a943384f4ccb0ca405d225eea9c8503d7861d47 Mon Sep 17 00:00:00 2001 From: Recolic Keghart <root@recolic.net> Date: Sat, 27 Apr 2019 03:34:58 -0700 Subject: [PATCH] add regMgr TODOS --- run.sh | 6 +- src/main/java/chocopy/pa3/CodeGenImpl.java | 67 +++++++++++++++++++--- 2 files changed, 60 insertions(+), 13 deletions(-) diff --git a/run.sh b/run.sh index 2c974e1..f1b231f 100755 --- a/run.sh +++ b/run.sh @@ -6,10 +6,8 @@ output="$3" classPath="chocopy-ref.jar:target/assignment.jar" -if [[ "$task" = parsetype ]]; then - java -cp "$classPath" chocopy.ChocoPy --pass=rr --out "$output" "$input" -elif [[ "$task" = codegen ]]; then - java -cp "$classPath" chocopy.ChocoPy --pass=..s --out "$output" "$input" +if [[ "$task" = codegen ]]; then + java -cp "$classPath" chocopy.ChocoPy --pass=rrs --out "$output" "$input" elif [[ "$task" = ass ]]; then java -cp "$classPath" chocopy.ChocoPy --pass=..s --run --dir src/test/data/pa3/sample/ --test | tee /tmp/cs164_ass.log # Should pass all positive test, else return error_code=2 diff --git a/src/main/java/chocopy/pa3/CodeGenImpl.java b/src/main/java/chocopy/pa3/CodeGenImpl.java index 30bf30d..08cb23f 100644 --- a/src/main/java/chocopy/pa3/CodeGenImpl.java +++ b/src/main/java/chocopy/pa3/CodeGenImpl.java @@ -47,7 +47,7 @@ public class CodeGenImpl extends CodeGenBase { backend.emitLW(reg, SP, 0, comment); backend.emitADDI(SP, SP, backend.getWordSize(), comment); } - public void emitCall(Label calledLabel, String comment) { + public void emitSavedFPCall(Label calledLabel, String comment) { // Arguments should be already pushed to stack. emitNoop(comment); emitPush(RA, "backup return address of parent."); @@ -55,14 +55,17 @@ public class CodeGenImpl extends CodeGenBase { backend.emitADDI(FP, SP, 2 * backend.getWordSize(), "Change FP to apply new frame."); // jal will set RA register properly. - // FIXME: Testing fucking silly $print - backend.emitADDI(SP, SP, 2 * backend.getWordSize(), "FUCKING SILLY BUILTIN CODE"); backend.emitJAL(calledLabel, "Call it!"); backend.emitADDI(SP, FP, -2 * backend.getWordSize(), "Revert all local variables on this dying frame."); emitPop(FP, "restore parent FP."); emitPop(RA, "restore parent return address."); } + public void emitCall(Label calledLabel, String comment) { + // Arguments should be already pushed to stack. + emitNoop(comment); + backend.emitJAL(calledLabel, "Call it!"); + } public void emitRet(String comment) { // All local variable should already be poped. // Return value should be in A0 @@ -73,7 +76,7 @@ public class CodeGenImpl extends CodeGenBase { emitNoop(comment); backend.emitLI(tmpReg, val, "INT VAL"); emitPush(tmpReg, null); - backend.emitLI(tmpReg, 0, "OBJECT HEAD - DISPATCH TBL = NULL"); + backend.emitLA(tmpReg, intClass.getDispatchTableLabel(), "OBJECT HEAD - DISPATCH TBL"); emitPush(tmpReg, null); backend.emitLI(tmpReg, 4, "OBJECT HEAD - SIZE = 3+1"); emitPush(tmpReg, null); @@ -85,7 +88,7 @@ public class CodeGenImpl extends CodeGenBase { emitNoop(comment); backend.emitLI(tmpReg, val ? 1 : 0, "BOOL VAL"); emitPush(tmpReg, null); - backend.emitLI(tmpReg, 0, "OBJECT HEAD - DISPATCH TBL = NULL"); + backend.emitLA(tmpReg, boolClass.getDispatchTableLabel(), "OBJECT HEAD - DISPATCH TBL"); emitPush(tmpReg, null); backend.emitLI(tmpReg, 4, "OBJECT HEAD - SIZE = 3+1"); emitPush(tmpReg, null); @@ -115,7 +118,7 @@ public class CodeGenImpl extends CodeGenBase { backend.emitLI(tmpReg, bytes.length, "STR ATTR - __len__"); emitPush(tmpReg, null); - backend.emitLI(tmpReg, 0, "OBJECT HEAD - DISPATCH TBL = NULL"); + backend.emitLA(tmpReg, strClass.getDispatchTableLabel(), "OBJECT HEAD - DISPATCH TBL"); emitPush(tmpReg, null); backend.emitLI(tmpReg, 3 + dataLen + 1, "OBJECT HEAD - SIZE"); emitPush(tmpReg, null); @@ -131,6 +134,34 @@ public class CodeGenImpl extends CodeGenBase { // because our toy compiler will only be tested on naive program. // manager won't swap register to stack smartly (with graph coloring technic), // because it doesn't worth my effort(nobody pay for that). + // + // FIXME: + // Update: Every function should have a register manager. + // before calling another function, the register manager should determine what register is used by `another function`, + // and backup them before calling the function. + // However, if the function is recursive, then the `another function` is not analyzed yet, + // then there's no way to know what register is in use in the `another function`. + // + // For a simple expr: `funcA() + funcB()`. If result of left operand is saved to T0, then in funcB, T0 is modified! + // that's bad. PLease fix the problem + // Maybe: result of funcA should be saved into callee-saved register S0-S8. Every function should save + // every callee-saved register on stack before using it. + // result of funcB (right operand) should be saved into caller-saved register T* or A*. + // + // However, If a function save a register S0 before using it, we write `push S0`. + // When you want to restore S0 (before return), the stack has already messed up!!! + // We should save S0 to somewhere. Usually, we can do the following: + // + // --- Push arguments... push arg1 ; push arg2 ; ....... --- + // --- I'm called! --- + // --- save FP --- + // --- I know I will use S0 and S1, save them to stack now... WAIT! HOW DO I KNOW I WILL USE S0 and S1??? --- FIXME + // --- I saw a expression, it uses S0... --- + // --- I saw a expression, it uses S1... --- + // --- Call others... --- + // --- SP(stack pointer) is messed up... I set it to FP+$(CorrectVal) --- + // --- pop S0 ; pop S1 --- + // --- restore FP, return --- private class registerManager { private Map<RiscVBackend.Register, Boolean> usageMap; // true if the reg is in use. registerManager() { @@ -149,7 +180,7 @@ public class CodeGenImpl extends CodeGenBase { usageMap.put(A5, false); usageMap.put(A6, false); usageMap.put(A7, false); - usageMap.put(A0, false); + // usageMap.put(A0, false); // used as return. not managed } public RiscVBackend.Register borrowOne() { @@ -314,10 +345,15 @@ public class CodeGenImpl extends CodeGenBase { SymbolInfo called = sym.get(node.function.name); if(called instanceof FuncInfo) { FuncInfo func = (FuncInfo) called; + if(func.getFuncName() != "print") { + throw new RuntimeException("Not implemented: emitCall doesn't allow calling user-defined function, because RA will be messed up."); + // TODO: analyze the reference compiler, to see why $print use 0(SP) as arg0, and how to call it with RA saved. + // https://piazza.com/class/jr5kaiy0u71499?cid=234 + } // TODO: Push the FUCKING arg0 (outter function frame ptr) List<RiscVBackend.Register> args_reg = new ArrayList<>(); for(Expr expr : node.args) { - // TODO: sub-expr may use stack. + // TODO: See register allocator TODOS. RiscVBackend.Register result = expr.dispatch(this); if(result == null) { throw new RuntimeException("NotImplemented: Expression " + expr.getClass().getName() + " returns null register."); @@ -347,7 +383,7 @@ public class CodeGenImpl extends CodeGenBase { RiscVBackend.Register leftRes = node.left.dispatch(this); RiscVBackend.Register rightRes = node.right.dispatch(this); if(leftRes == null || rightRes == null) - throw new RuntimeException("NOT IMPL"); + return null; switch(node.operator) { case "+": if(node.left.getInferredType().equals(SymbolType.INT_TYPE)) { @@ -397,6 +433,19 @@ public class CodeGenImpl extends CodeGenBase { return null; } + @Override + public RiscVBackend.Register analyze(Identifier node) { + SymbolInfo id = sym.get(node.name); + if(id instanceof GlobalVarInfo) { + GlobalVarInfo globalVarInfo = (GlobalVarInfo) id; + RiscVBackend.Register tmpReg = regMgr.borrowOne(); + backend.emitLA(tmpReg, globalVarInfo.getLabel(), "Load address of the global var."); + return tmpReg; + } + // FIXME: not implemented + return null; + } + @Override public RiscVBackend.Register analyze(IntegerLiteral node) { // emitConstant(node, ValueType.INT_TYPE, "Set constant int literal."); -- GitLab