Skip to content
Snippets Groups Projects
Verified Commit 5a943384 authored by Recolic Keghart's avatar Recolic Keghart
Browse files

add regMgr TODOS

parent 772b0697
No related branches found
No related tags found
No related merge requests found
Pipeline #270 passed with warnings with stages
in 15 minutes and 30 seconds
...@@ -6,10 +6,8 @@ output="$3" ...@@ -6,10 +6,8 @@ output="$3"
classPath="chocopy-ref.jar:target/assignment.jar" classPath="chocopy-ref.jar:target/assignment.jar"
if [[ "$task" = parsetype ]]; then if [[ "$task" = codegen ]]; then
java -cp "$classPath" chocopy.ChocoPy --pass=rr --out "$output" "$input" java -cp "$classPath" chocopy.ChocoPy --pass=rrs --out "$output" "$input"
elif [[ "$task" = codegen ]]; then
java -cp "$classPath" chocopy.ChocoPy --pass=..s --out "$output" "$input"
elif [[ "$task" = ass ]]; then elif [[ "$task" = ass ]]; then
java -cp "$classPath" chocopy.ChocoPy --pass=..s --run --dir src/test/data/pa3/sample/ --test | tee /tmp/cs164_ass.log 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 # Should pass all positive test, else return error_code=2
......
...@@ -47,7 +47,7 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -47,7 +47,7 @@ public class CodeGenImpl extends CodeGenBase {
backend.emitLW(reg, SP, 0, comment); backend.emitLW(reg, SP, 0, comment);
backend.emitADDI(SP, SP, backend.getWordSize(), 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. // Arguments should be already pushed to stack.
emitNoop(comment); emitNoop(comment);
emitPush(RA, "backup return address of parent."); emitPush(RA, "backup return address of parent.");
...@@ -55,14 +55,17 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -55,14 +55,17 @@ public class CodeGenImpl extends CodeGenBase {
backend.emitADDI(FP, SP, 2 * backend.getWordSize(), "Change FP to apply new frame."); backend.emitADDI(FP, SP, 2 * backend.getWordSize(), "Change FP to apply new frame.");
// jal will set RA register properly. // 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.emitJAL(calledLabel, "Call it!");
backend.emitADDI(SP, FP, -2 * backend.getWordSize(), "Revert all local variables on this dying frame."); backend.emitADDI(SP, FP, -2 * backend.getWordSize(), "Revert all local variables on this dying frame.");
emitPop(FP, "restore parent FP."); emitPop(FP, "restore parent FP.");
emitPop(RA, "restore parent return address."); 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) { public void emitRet(String comment) {
// All local variable should already be poped. // All local variable should already be poped.
// Return value should be in A0 // Return value should be in A0
...@@ -73,7 +76,7 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -73,7 +76,7 @@ public class CodeGenImpl extends CodeGenBase {
emitNoop(comment); emitNoop(comment);
backend.emitLI(tmpReg, val, "INT VAL"); backend.emitLI(tmpReg, val, "INT VAL");
emitPush(tmpReg, null); emitPush(tmpReg, null);
backend.emitLI(tmpReg, 0, "OBJECT HEAD - DISPATCH TBL = NULL"); backend.emitLA(tmpReg, intClass.getDispatchTableLabel(), "OBJECT HEAD - DISPATCH TBL");
emitPush(tmpReg, null); emitPush(tmpReg, null);
backend.emitLI(tmpReg, 4, "OBJECT HEAD - SIZE = 3+1"); backend.emitLI(tmpReg, 4, "OBJECT HEAD - SIZE = 3+1");
emitPush(tmpReg, null); emitPush(tmpReg, null);
...@@ -85,7 +88,7 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -85,7 +88,7 @@ public class CodeGenImpl extends CodeGenBase {
emitNoop(comment); emitNoop(comment);
backend.emitLI(tmpReg, val ? 1 : 0, "BOOL VAL"); backend.emitLI(tmpReg, val ? 1 : 0, "BOOL VAL");
emitPush(tmpReg, null); emitPush(tmpReg, null);
backend.emitLI(tmpReg, 0, "OBJECT HEAD - DISPATCH TBL = NULL"); backend.emitLA(tmpReg, boolClass.getDispatchTableLabel(), "OBJECT HEAD - DISPATCH TBL");
emitPush(tmpReg, null); emitPush(tmpReg, null);
backend.emitLI(tmpReg, 4, "OBJECT HEAD - SIZE = 3+1"); backend.emitLI(tmpReg, 4, "OBJECT HEAD - SIZE = 3+1");
emitPush(tmpReg, null); emitPush(tmpReg, null);
...@@ -115,7 +118,7 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -115,7 +118,7 @@ public class CodeGenImpl extends CodeGenBase {
backend.emitLI(tmpReg, bytes.length, "STR ATTR - __len__"); backend.emitLI(tmpReg, bytes.length, "STR ATTR - __len__");
emitPush(tmpReg, null); emitPush(tmpReg, null);
backend.emitLI(tmpReg, 0, "OBJECT HEAD - DISPATCH TBL = NULL"); backend.emitLA(tmpReg, strClass.getDispatchTableLabel(), "OBJECT HEAD - DISPATCH TBL");
emitPush(tmpReg, null); emitPush(tmpReg, null);
backend.emitLI(tmpReg, 3 + dataLen + 1, "OBJECT HEAD - SIZE"); backend.emitLI(tmpReg, 3 + dataLen + 1, "OBJECT HEAD - SIZE");
emitPush(tmpReg, null); emitPush(tmpReg, null);
...@@ -131,6 +134,34 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -131,6 +134,34 @@ public class CodeGenImpl extends CodeGenBase {
// because our toy compiler will only be tested on naive program. // because our toy compiler will only be tested on naive program.
// manager won't swap register to stack smartly (with graph coloring technic), // manager won't swap register to stack smartly (with graph coloring technic),
// because it doesn't worth my effort(nobody pay for that). // 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 class registerManager {
private Map<RiscVBackend.Register, Boolean> usageMap; // true if the reg is in use. private Map<RiscVBackend.Register, Boolean> usageMap; // true if the reg is in use.
registerManager() { registerManager() {
...@@ -149,7 +180,7 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -149,7 +180,7 @@ public class CodeGenImpl extends CodeGenBase {
usageMap.put(A5, false); usageMap.put(A5, false);
usageMap.put(A6, false); usageMap.put(A6, false);
usageMap.put(A7, false); usageMap.put(A7, false);
usageMap.put(A0, false); // usageMap.put(A0, false); // used as return. not managed
} }
public RiscVBackend.Register borrowOne() { public RiscVBackend.Register borrowOne() {
...@@ -314,10 +345,15 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -314,10 +345,15 @@ public class CodeGenImpl extends CodeGenBase {
SymbolInfo called = sym.get(node.function.name); SymbolInfo called = sym.get(node.function.name);
if(called instanceof FuncInfo) { if(called instanceof FuncInfo) {
FuncInfo func = (FuncInfo) called; 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) // TODO: Push the FUCKING arg0 (outter function frame ptr)
List<RiscVBackend.Register> args_reg = new ArrayList<>(); List<RiscVBackend.Register> args_reg = new ArrayList<>();
for(Expr expr : node.args) { for(Expr expr : node.args) {
// TODO: sub-expr may use stack. // TODO: See register allocator TODOS.
RiscVBackend.Register result = expr.dispatch(this); RiscVBackend.Register result = expr.dispatch(this);
if(result == null) { if(result == null) {
throw new RuntimeException("NotImplemented: Expression " + expr.getClass().getName() + " returns null register."); throw new RuntimeException("NotImplemented: Expression " + expr.getClass().getName() + " returns null register.");
...@@ -347,7 +383,7 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -347,7 +383,7 @@ public class CodeGenImpl extends CodeGenBase {
RiscVBackend.Register leftRes = node.left.dispatch(this); RiscVBackend.Register leftRes = node.left.dispatch(this);
RiscVBackend.Register rightRes = node.right.dispatch(this); RiscVBackend.Register rightRes = node.right.dispatch(this);
if(leftRes == null || rightRes == null) if(leftRes == null || rightRes == null)
throw new RuntimeException("NOT IMPL"); return null;
switch(node.operator) { switch(node.operator) {
case "+": case "+":
if(node.left.getInferredType().equals(SymbolType.INT_TYPE)) { if(node.left.getInferredType().equals(SymbolType.INT_TYPE)) {
...@@ -397,6 +433,19 @@ public class CodeGenImpl extends CodeGenBase { ...@@ -397,6 +433,19 @@ public class CodeGenImpl extends CodeGenBase {
return null; 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 @Override
public RiscVBackend.Register analyze(IntegerLiteral node) { public RiscVBackend.Register analyze(IntegerLiteral node) {
// emitConstant(node, ValueType.INT_TYPE, "Set constant int literal."); // emitConstant(node, ValueType.INT_TYPE, "Set constant int literal.");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment