diff --git a/run.sh b/run.sh
index 2c974e1f3880de01aebf9003be4c6149084d00b0..f1b231f6ac71a60726de66e7d05c7cdc12dc6574 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 30bf30d011740dc45c67922a6978f4209c761096..08cb23f6a73eef7d1ec60f379c2a368c1970c03a 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.");