From 7b231d9998dec1c4150db565b1b7da939d25c47c Mon Sep 17 00:00:00 2001 From: Xingyu Xie Date: Sun, 5 Jan 2020 23:01:35 +0800 Subject: [PATCH 1/3] Now oct and hex are recognized. --- src/main/scala/decaf/frontend/parsing/Lexer.scala | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/scala/decaf/frontend/parsing/Lexer.scala b/src/main/scala/decaf/frontend/parsing/Lexer.scala index 78802af..06f662e 100644 --- a/src/main/scala/decaf/frontend/parsing/Lexer.scala +++ b/src/main/scala/decaf/frontend/parsing/Lexer.scala @@ -36,7 +36,13 @@ class Lexer(in: CharStream, errorIssuer: ErrorIssuer) extends DecafLexer(in) { val token = super.emit var literal = "0" try { - literal = token.getText.toInt.toString + val text = token.getText + literal = + if (text.startsWith("0x")) + Integer.parseInt(text.substring(2), 16).toString + else if (text.startsWith("0") && text.size > 1) + Integer.parseInt(text.substring(1), 16).toString + else text.toInt.toString } catch { case _: NumberFormatException => // not a valid 32-bit integer errorIssuer.issue(new IntTooLargeError(token.getText, getPos(token))) From ebef4a0afd0e1ae916609306862caf8eed98cc23 Mon Sep 17 00:00:00 2001 From: TA Date: Mon, 13 Jan 2020 18:24:58 +0800 Subject: [PATCH 2/3] Backfill the positions of local data in the current frame and arguments in the last frame. --- .gitignore | 1 + src/main/java/decaf/lowlevel/Mips.java | 91 +++++++++----- .../java/decaf/lowlevel/tac/FuncVisitor.java | 28 +++-- .../java/decaf/lowlevel/tac/TacInstr.java | 119 +++++++++++------- .../decaf/backend/asm/SubroutineEmitter.scala | 8 ++ .../asm/mips/MipsSubroutineEmitter.scala | 91 ++++++++++---- .../decaf/backend/reg/BruteRegAlloc.scala | 7 ++ 7 files changed, 225 insertions(+), 120 deletions(-) diff --git a/.gitignore b/.gitignore index 1df0e25..f1f8a43 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ project/plugins/project/ .scala_dependencies .worksheet .idea/ +.metals/ # Tmp files *.tac diff --git a/src/main/java/decaf/lowlevel/Mips.java b/src/main/java/decaf/lowlevel/Mips.java index d74641f..5edf4a7 100644 --- a/src/main/java/decaf/lowlevel/Mips.java +++ b/src/main/java/decaf/lowlevel/Mips.java @@ -47,19 +47,13 @@ public class Mips { public static final Reg S8 = new Reg(30, "$s8"); // also called $fp, but used as an additional saved register public static final Reg RA = new Reg(31, "$ra"); // return address - public static final Reg[] callerSaved = new Reg[]{ - V1, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 - }; + public static final Reg[] callerSaved = new Reg[] { V1, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9 }; - public static final Reg[] calleeSaved = new Reg[]{ - S0, S1, S2, S3, S4, S5, S6, S7, S8 - }; + public static final Reg[] calleeSaved = new Reg[] { S0, S1, S2, S3, S4, S5, S6, S7, S8 }; public static final Reg[] allocatableRegs = ArrayUtils.addAll(callerSaved, calleeSaved); - public static final Reg[] argRegs = new Reg[]{ - A0, A1, A2, A3 - }; + public static final Reg[] argRegs = new Reg[] { A0, A1, A2, A3 }; // Instructions @@ -81,7 +75,7 @@ private static String format(String op, String fmt, Object... args) { public static class Move extends PseudoInstr { public Move(Temp dst, Temp src) { - super(new Temp[]{dst}, new Temp[]{src}); + super(new Temp[] { dst }, new Temp[] { src }); } @Override @@ -97,7 +91,7 @@ public enum UnaryOp { public static class Unary extends PseudoInstr { public Unary(UnaryOp op, Temp dst, Temp src) { - super(new Temp[]{dst}, new Temp[]{src}); + super(new Temp[] { dst }, new Temp[] { src }); this.op = op.toString().toLowerCase(); } @@ -110,15 +104,13 @@ public String toString() { } public enum BinaryOp { - ADD, SUB, MUL, DIV, REM, - SGT, SGE, SEQ, SNE, SLE, SLT, - AND, OR + ADD, SUB, MUL, DIV, REM, SGT, SGE, SEQ, SNE, SLE, SLT, AND, OR } public static class Binary extends PseudoInstr { public Binary(BinaryOp op, Temp dst, Temp src0, Temp src1) { - super(new Temp[]{dst}, new Temp[]{src0, src1}); + super(new Temp[] { dst }, new Temp[] { src0, src1 }); this.op = op.toString().toLowerCase(); } @@ -137,7 +129,7 @@ public enum BranchOp { public static class Branch extends PseudoInstr { public Branch(BranchOp op, Temp src, Label to) { - super(Kind.COND_JMP, new Temp[]{}, new Temp[]{src}, to); + super(Kind.COND_JMP, new Temp[] {}, new Temp[] { src }, to); this.op = op.toString().toLowerCase(); } @@ -152,7 +144,7 @@ public String toString() { public static class Jump extends PseudoInstr { public Jump(Label to) { - super(Kind.JMP, new Temp[]{}, new Temp[]{}, to); + super(Kind.JMP, new Temp[] {}, new Temp[] {}, to); } @Override @@ -162,12 +154,13 @@ public String toString() { } /** - * The special jump-to-epilogue instruction {@code j epilogue} is regarded as a return statement. + * The special jump-to-epilogue instruction {@code j epilogue} is regarded as a + * return statement. */ public static class JumpToEpilogue extends PseudoInstr { public JumpToEpilogue(Label label) { - super(Kind.RET, new Temp[]{}, new Temp[]{}, new Label(label + EPILOGUE_SUFFIX)); + super(Kind.RET, new Temp[] {}, new Temp[] {}, new Label(label + EPILOGUE_SUFFIX)); } @Override @@ -179,7 +172,7 @@ public String toString() { public static class JumpAndLink extends PseudoInstr { public JumpAndLink(Label to) { - super(Kind.SEQ, new Temp[]{}, new Temp[]{}, to); + super(Kind.SEQ, new Temp[] {}, new Temp[] {}, to); } @Override @@ -191,7 +184,7 @@ public String toString() { public static class JumpAndLinkReg extends PseudoInstr { public JumpAndLinkReg(Temp src) { - super(new Temp[]{}, new Temp[]{src}); + super(new Temp[] {}, new Temp[] { src }); } @Override @@ -203,7 +196,7 @@ public String toString() { public static class LoadWord extends PseudoInstr { public LoadWord(Temp dst, Temp base, int offset) { - super(new Temp[]{dst}, new Temp[]{base}); + super(new Temp[] { dst }, new Temp[] { base }); this.offset = offset; } @@ -218,7 +211,7 @@ public String toString() { public static class StoreWord extends PseudoInstr { public StoreWord(Temp src, Temp base, int offset) { - super(new Temp[]{}, new Temp[]{src, base}); + super(new Temp[] {}, new Temp[] { src, base }); this.offset = offset; } @@ -233,7 +226,7 @@ public String toString() { public static class LoadImm extends PseudoInstr { public LoadImm(Temp dst, int value) { - super(new Temp[]{dst}, new Temp[]{}); + super(new Temp[] { dst }, new Temp[] {}); this.value = value; } @@ -248,7 +241,7 @@ public String toString() { public static class LoadAddr extends PseudoInstr { public LoadAddr(Temp dst, Label label) { - super(Kind.SEQ, new Temp[]{dst}, new Temp[]{}, label); + super(Kind.SEQ, new Temp[] { dst }, new Temp[] {}, label); } @Override @@ -272,7 +265,7 @@ public String toString() { public static class Syscall extends NativeInstr { public Syscall() { - super(new Reg[]{}, new Reg[]{}); + super(new Reg[] {}, new Reg[] {}); } @Override @@ -284,7 +277,7 @@ public String toString() { public static class NativeMove extends NativeInstr { public NativeMove(Reg dst, Reg src) { - super(new Reg[]{dst}, new Reg[]{src}); + super(new Reg[] { dst }, new Reg[] { src }); } @Override @@ -296,10 +289,26 @@ public String toString() { public static class NativeLoadWord extends NativeInstr { public NativeLoadWord(Reg dst, Reg base, int offset) { - super(new Reg[]{dst}, new Reg[]{base}); + super(new Reg[] { dst }, new Reg[] { base }); this.offset = offset; } + public NativeLoadWord(Reg dst, Reg base, int offset, boolean isArgOrLocal) { + super(new Reg[] { dst }, new Reg[] { base }); + this.offset = offset; + this.isArgOrLocal = isArgOrLocal; + } + + private boolean isArgOrLocal; // [true] represents argument, and [false] represents local data. + + public void backfill(int maxArgsNum, int frameLength) { + if (isArgOrLocal) { + offset += frameLength; + } else { + offset += Math.max(maxArgsNum - 4, 0) * 4; + } + } + private int offset; @Override @@ -311,10 +320,26 @@ public String toString() { public static class NativeStoreWord extends NativeInstr { public NativeStoreWord(Reg src, Reg base, int offset) { - super(new Reg[]{}, new Reg[]{src, base}); + super(new Reg[] {}, new Reg[] { src, base }); this.offset = offset; } + public NativeStoreWord(Reg src, Reg base, int offset, boolean isArgOrLocal) { + super(new Reg[] {}, new Reg[] { src, base }); + this.offset = offset; + this.isArgOrLocal = isArgOrLocal; + } + + private boolean isArgOrLocal; + + public void backfill(int maxArgsNum, int frameLength) { + if (isArgOrLocal) { + offset += frameLength; + } else { + offset += Math.max(maxArgsNum - 4, 0) * 4; + } + } + private int offset; @Override @@ -324,13 +349,13 @@ public String toString() { } /** - * Since the only possible usage of the {@code jr} is to return a subroutine with {@code jr $ra}. - * Why not simply call this "Return"? + * Since the only possible usage of the {@code jr} is to return a subroutine + * with {@code jr $ra}. Why not simply call this "Return"? */ public static class NativeReturn extends NativeInstr { public NativeReturn() { - super(Kind.RET, new Reg[]{RA}, new Reg[]{}, null); + super(Kind.RET, new Reg[] { RA }, new Reg[] {}, null); } @Override @@ -342,7 +367,7 @@ public String toString() { public static class SPAdd extends NativeInstr { public SPAdd(int offset) { - super(new Reg[]{SP}, new Reg[]{SP}); + super(new Reg[] { SP }, new Reg[] { SP }); this.offset = offset; } diff --git a/src/main/java/decaf/lowlevel/tac/FuncVisitor.java b/src/main/java/decaf/lowlevel/tac/FuncVisitor.java index e93fb35..4a09a99 100644 --- a/src/main/java/decaf/lowlevel/tac/FuncVisitor.java +++ b/src/main/java/decaf/lowlevel/tac/FuncVisitor.java @@ -161,7 +161,7 @@ public void visitReturn(Temp value) { public Temp visitNewClass(String clazz) { var temp = freshTemp(); var entry = ctx.getConstructorLabel(clazz); - func.add(new TacInstr.DirectCall(temp, entry)); + func.add(new TacInstr.DirectCall(temp, entry, 1)); return temp; } @@ -195,7 +195,8 @@ public void visitMemberWrite(Temp object, String clazz, String variable, Temp va * @param clazz class name * @param method member method name * @param args argument temps - * @param needReturn do we need a fresh temp to store the return value? (default false) + * @param needReturn do we need a fresh temp to store the return value? (default + * false) * @return the fresh temp if we need return (or else null) */ public Temp visitMemberCall(Temp object, String clazz, String method, List args, boolean needReturn) { @@ -209,9 +210,9 @@ public Temp visitMemberCall(Temp object, String clazz, String method, List } if (needReturn) { temp = freshTemp(); - func.add(new TacInstr.IndirectCall(temp, entry)); + func.add(new TacInstr.IndirectCall(temp, entry, args.size())); } else { - func.add(new TacInstr.IndirectCall(entry)); + func.add(new TacInstr.IndirectCall(entry, args.size())); } return temp; } @@ -229,7 +230,8 @@ public void visitMemberCall(Temp object, String clazz, String method, List * @param clazz class name * @param method method name * @param args argument temps - * @param needReturn do we need a fresh temp to store the return value? (default false) + * @param needReturn do we need a fresh temp to store the return value? (default + * false) * @return the fresh temp if we need return (or else null) */ public Temp visitStaticCall(String clazz, String method, List args, boolean needReturn) { @@ -241,9 +243,9 @@ public Temp visitStaticCall(String clazz, String method, List args, boolea } if (needReturn) { temp = freshTemp(); - func.add(new TacInstr.DirectCall(temp, entry)); + func.add(new TacInstr.DirectCall(temp, entry, args.size())); } else { - func.add(new TacInstr.DirectCall(entry)); + func.add(new TacInstr.DirectCall(entry, args.size())); } return temp; } @@ -259,7 +261,8 @@ public void visitStaticCall(String clazz, String method, List args) { * Append instructions to invoke an intrinsic method. * * @param func intrinsic function - * @param needReturn do we need a fresh temp to store the return value? (default false) + * @param needReturn do we need a fresh temp to store the return value? (default + * false) * @param args argument temps * @return the fresh temp if we need return (or else null) */ @@ -271,9 +274,9 @@ public Temp visitIntrinsicCall(Intrinsic func, boolean needReturn, Temp... args) } if (needReturn) { temp = freshTemp(); - this.func.add(new TacInstr.DirectCall(temp, func)); + this.func.add(new TacInstr.DirectCall(temp, func, args.length)); } else { - this.func.add(new TacInstr.DirectCall(func)); + this.func.add(new TacInstr.DirectCall(func, args.length)); } return temp; } @@ -394,8 +397,9 @@ public Temp freshTemp() { /** * Get the temp for the {@code index}-th argument. *

- * According to TAC virtual machine calling convention, for a function with {@code n} arguments, the temps with id - * from 0 to {@code n - 1} are reserved for passing these {@code n} arguments. + * According to TAC virtual machine calling convention, for a function with + * {@code n} arguments, the temps with id from 0 to {@code n - 1} are reserved + * for passing these {@code n} arguments. * * @param index argument index, start from 0 * @return temp diff --git a/src/main/java/decaf/lowlevel/tac/TacInstr.java b/src/main/java/decaf/lowlevel/tac/TacInstr.java index da1777b..0d0f7ef 100644 --- a/src/main/java/decaf/lowlevel/tac/TacInstr.java +++ b/src/main/java/decaf/lowlevel/tac/TacInstr.java @@ -106,8 +106,9 @@ default void visitOthers(TacInstr instr) { /** * Assignment. + * *

-     *     dst = src
+     * dst = src
      * 
*/ public static class Assign extends TacInstr { @@ -115,7 +116,7 @@ public static class Assign extends TacInstr { public final Temp src; public Assign(Temp dst, Temp src) { - super(new Temp[]{dst}, new Temp[]{src}); + super(new Temp[] { dst }, new Temp[] { src }); this.dst = dst; this.src = src; } @@ -133,6 +134,7 @@ public String toString() { /** * Load a virtual table. + * *
      *     dst = VTABLE<vtbl>
      * 
@@ -142,7 +144,7 @@ public static class LoadVTbl extends TacInstr { public final VTable vtbl; public LoadVTbl(Temp dst, VTable vtbl) { - super(new Temp[]{dst}, new Temp[]{}); + super(new Temp[] { dst }, new Temp[] {}); this.dst = dst; this.vtbl = vtbl; } @@ -160,8 +162,9 @@ public String toString() { /** * Load a 32-bit signed integer. + * *
-     *     dst = value
+     * dst = value
      * 
*/ public static class LoadImm4 extends TacInstr { @@ -169,7 +172,7 @@ public static class LoadImm4 extends TacInstr { public final int value; public LoadImm4(Temp dst, int value) { - super(new Temp[]{dst}, new Temp[]{}); + super(new Temp[] { dst }, new Temp[] {}); this.dst = dst; this.value = value; } @@ -187,8 +190,9 @@ public String toString() { /** * Load constant string. + * *
-     *     dst = value
+     * dst = value
      * 
*/ public static class LoadStrConst extends TacInstr { @@ -196,7 +200,7 @@ public static class LoadStrConst extends TacInstr { public final String value; public LoadStrConst(Temp dst, String value) { - super(new Temp[]{dst}, new Temp[]{}); + super(new Temp[] { dst }, new Temp[] {}); this.dst = dst; this.value = value; } @@ -214,6 +218,7 @@ public String toString() { /** * Unary instruction. + * *
      *     dst = op operand
      * 
@@ -228,7 +233,7 @@ public enum Op { } public Unary(Op op, Temp dst, Temp operand) { - super(new Temp[]{dst}, new Temp[]{operand}); + super(new Temp[] { dst }, new Temp[] { operand }); this.op = op; this.dst = dst; this.operand = operand; @@ -242,8 +247,8 @@ public void accept(Visitor v) { @Override public String toString() { var opStr = switch (op) { - case NEG -> "-"; - case LNOT -> "!"; + case NEG -> "-"; + case LNOT -> "!"; }; return String.format("%s = %s %s", dst, opStr, operand); } @@ -251,6 +256,7 @@ public String toString() { /** * Binary instruction. + * *
      *     dst = (lhs op rhs)
      * 
@@ -266,7 +272,7 @@ public enum Op { } public Binary(Op op, Temp dst, Temp lhs, Temp rhs) { - super(new Temp[]{dst}, new Temp[]{lhs, rhs}); + super(new Temp[] { dst }, new Temp[] { lhs, rhs }); this.op = op; this.dst = dst; this.lhs = lhs; @@ -281,19 +287,19 @@ public void accept(Visitor v) { @Override public String toString() { var opStr = switch (op) { - case ADD -> "+"; - case SUB -> "-"; - case MUL -> "*"; - case DIV -> "/"; - case MOD -> "%"; - case EQU -> "=="; - case NEQ -> "!="; - case LES -> "<"; - case LEQ -> "<="; - case GTR -> ">"; - case GEQ -> ">="; - case LAND -> "&&"; - case LOR -> "||"; + case ADD -> "+"; + case SUB -> "-"; + case MUL -> "*"; + case DIV -> "/"; + case MOD -> "%"; + case EQU -> "=="; + case NEQ -> "!="; + case LES -> "<"; + case LEQ -> "<="; + case GTR -> ">"; + case GEQ -> ">="; + case LAND -> "&&"; + case LOR -> "||"; }; return String.format("%s = (%s %s %s)", dst, lhs, opStr, rhs); } @@ -301,6 +307,7 @@ public String toString() { /** * Branch instruction. + * *
      *     branch target
      * 
@@ -309,7 +316,7 @@ public static class Branch extends TacInstr { public final Label target; public Branch(Label target) { - super(Kind.JMP, new Temp[]{}, new Temp[]{}, target); + super(Kind.JMP, new Temp[] {}, new Temp[] {}, target); this.target = target; } @@ -326,6 +333,7 @@ public String toString() { /** * Branch instruction. + * *
      *     if (cond == 0) branch target
      *     if (cond != 0) branch target
@@ -341,7 +349,7 @@ public enum Op {
         }
 
         public CondBranch(Op op, Temp cond, Label target) {
-            super(Kind.COND_JMP, new Temp[]{}, new Temp[]{cond}, target);
+            super(Kind.COND_JMP, new Temp[] {}, new Temp[] { cond }, target);
             this.op = op;
             this.cond = cond;
             this.target = target;
@@ -355,8 +363,8 @@ public void accept(Visitor v) {
         @Override
         public String toString() {
             var opStr = switch (op) {
-                case BEQZ -> "== 0";
-                case BNEZ -> "!= 0";
+            case BEQZ -> "== 0";
+            case BNEZ -> "!= 0";
             };
             return String.format("if (%s %s) branch %s", cond, opStr, target.prettyString());
         }
@@ -364,6 +372,7 @@ public String toString() {
 
     /**
      * Return instruction.
+     * 
      * 
      *     return value?
      * 
@@ -372,12 +381,12 @@ public static class Return extends TacInstr { public final Optional value; public Return(Temp value) { - super(Kind.RET, new Temp[]{}, new Temp[]{value}, null); + super(Kind.RET, new Temp[] {}, new Temp[] { value }, null); this.value = Optional.of(value); } public Return() { - super(Kind.RET, new Temp[]{}, new Temp[]{}, null); + super(Kind.RET, new Temp[] {}, new Temp[] {}, null); this.value = Optional.empty(); } @@ -397,6 +406,7 @@ public String toString() { /** * Push a parameter. + * *
      *     parm value
      * 
@@ -405,7 +415,7 @@ public static class Parm extends TacInstr { public final Temp value; public Parm(Temp value) { - super(new Temp[]{}, new Temp[]{value}); + super(new Temp[] {}, new Temp[] { value }); this.value = value; } @@ -422,6 +432,7 @@ public String toString() { /** * Call by address (which is stored in a temp). + * *
      *     {dst =}? call entry
      * 
@@ -429,17 +440,20 @@ public String toString() { public static class IndirectCall extends TacInstr { public final Optional dst; public final Temp entry; + public final Integer numArgs; - public IndirectCall(Temp dst, Temp entry) { - super(new Temp[]{dst}, new Temp[]{entry}); + public IndirectCall(Temp dst, Temp entry, Integer numArgs) { + super(new Temp[] { dst }, new Temp[] { entry }); this.dst = Optional.of(dst); this.entry = entry; + this.numArgs = numArgs; } - public IndirectCall(Temp entry) { - super(new Temp[]{}, new Temp[]{entry}); + public IndirectCall(Temp entry, Integer numArgs) { + super(new Temp[] {}, new Temp[] { entry }); this.dst = Optional.empty(); this.entry = entry; + this.numArgs = numArgs; } @Override @@ -458,6 +472,7 @@ public String toString() { /** * Call by label. + * *
      *     {dst =}? call entry
      * 
@@ -465,29 +480,34 @@ public String toString() { public static class DirectCall extends TacInstr { public final Optional dst; public final Label entry; + public final Integer numArgs; - public DirectCall(Temp dst, Label entry) { - super(new Temp[]{dst}, new Temp[]{}); + public DirectCall(Temp dst, Label entry, Integer numArgs) { + super(new Temp[] { dst }, new Temp[] {}); this.dst = Optional.of(dst); this.entry = entry; + this.numArgs = numArgs; } - public DirectCall(Label entry) { - super(new Temp[]{}, new Temp[]{}); + public DirectCall(Label entry, Integer numArgs) { + super(new Temp[] {}, new Temp[] {}); this.dst = Optional.empty(); this.entry = entry; + this.numArgs = numArgs; } - public DirectCall(Temp dst, Intrinsic intrinsic) { - super(new Temp[]{dst}, new Temp[]{}); + public DirectCall(Temp dst, Intrinsic intrinsic, Integer numArgs) { + super(new Temp[] { dst }, new Temp[] {}); this.dst = Optional.of(dst); this.entry = intrinsic.entry; + this.numArgs = numArgs; } - public DirectCall(Intrinsic intrinsic) { - super(new Temp[]{}, new Temp[]{}); + public DirectCall(Intrinsic intrinsic, Integer numArgs) { + super(new Temp[] {}, new Temp[] {}); this.dst = Optional.empty(); this.entry = intrinsic.entry; + this.numArgs = numArgs; } @Override @@ -506,6 +526,7 @@ public String toString() { /** * Memory access: load/store. + * *
      *     dst = *(base + offset)
      *     *(base + offset) = dst
@@ -522,8 +543,8 @@ public enum Op {
         }
 
         public Memory(Op op, Temp dst, Temp base, int offset) {
-            super(op.equals(Op.LOAD) ? new Temp[]{dst} : new Temp[]{},
-                    op.equals(Op.LOAD) ? new Temp[]{base} : new Temp[]{dst, base});
+            super(op.equals(Op.LOAD) ? new Temp[] { dst } : new Temp[] {},
+                    op.equals(Op.LOAD) ? new Temp[] { base } : new Temp[] { dst, base });
             this.op = op;
             this.dst = dst;
             this.base = base;
@@ -540,14 +561,15 @@ public String toString() {
             var sign = offset >= 0 ? "+" : "-";
             var value = offset >= 0 ? offset : -offset;
             return switch (op) {
-                case LOAD -> String.format("%s = *(%s %s %d)", dst, base, sign, value);
-                case STORE -> String.format("*(%s %s %d) = %s", base, sign, offset, dst);
+            case LOAD -> String.format("%s = *(%s %s %d)", dst, base, sign, value);
+            case STORE -> String.format("*(%s %s %d) = %s", base, sign, offset, dst);
             };
         }
     }
 
     /**
      * Comment.
+     * 
      * 
      *     memo 'msg'
      * 
@@ -556,7 +578,7 @@ public static class Memo extends TacInstr { final String msg; public Memo(String msg) { - super(new Temp[]{}, new Temp[]{}); + super(new Temp[] {}, new Temp[] {}); this.msg = msg; } @@ -573,6 +595,7 @@ public String toString() { /** * Label. + * *
      * label:
      * 
diff --git a/src/main/scala/decaf/backend/asm/SubroutineEmitter.scala b/src/main/scala/decaf/backend/asm/SubroutineEmitter.scala index 541b5d1..3f0cf42 100644 --- a/src/main/scala/decaf/backend/asm/SubroutineEmitter.scala +++ b/src/main/scala/decaf/backend/asm/SubroutineEmitter.scala @@ -2,6 +2,7 @@ package decaf.backend.asm import decaf.lowlevel.AsmCodePrinter import decaf.lowlevel.instr.{NativeInstr, Reg, Temp} +import decaf.lowlevel.tac.TacInstr import decaf.lowlevel.label.Label /** @@ -28,6 +29,13 @@ abstract class SubroutineEmitter protected(val emitter: AsmEmitter, var info: Su */ def emitLoadFromStack(dst: Reg, src: Temp): Unit + /** + * Load the information of call + * + * @param instr instruction + */ + def emitCall(instr: Int): Unit + /** * Append an assembly instruction that copies value between two registers. * diff --git a/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala b/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala index ea6c262..71cac33 100644 --- a/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala +++ b/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala @@ -3,6 +3,7 @@ package decaf.backend.asm.mips import decaf.backend.asm.{SubroutineEmitter, SubroutineInfo} import decaf.lowlevel.Mips import decaf.lowlevel.instr.{NativeInstr, Reg, Temp} +import decaf.lowlevel.tac.TacInstr import decaf.lowlevel.label.Label import scala.collection.mutable @@ -33,29 +34,45 @@ class MipsSubroutineEmitter private[mips](emitter: MipsAsmEmitter, info: Subrout extends SubroutineEmitter(emitter, info) { override def emitStoreToStack(src: Reg, temp: Temp): Unit = { - if (!offsets.contains(temp)) { - if (temp.index < info.numArgs) { // Always map arg `i` to `SP + 4 * i`. - offsets(temp) = 4 * temp.index - } - else { - offsets(temp) = nextLocalOffset - nextLocalOffset += 4 - } + var isArgOrLocal = true + if (temp.index < info.numArgs) { // Always map arg `i` to `SP + 4 * i`. + if (!offsets.contains(temp)) { + offsets(temp) = 4 * temp.index + } + isArgOrLocal = true } - buf += new Mips.NativeStoreWord(src, Mips.SP, offsets(temp)) + else { + if (!offsets.contains(temp)) { + offsets(temp) = nextLocalOffset + nextLocalOffset += 4 + } + isArgOrLocal = false + } + buf += new Mips.NativeStoreWord(src, Mips.SP, offsets(temp), isArgOrLocal) } override def emitLoadFromStack(dst: Reg, src: Temp): Unit = { - if (!offsets.contains(src)) { - if (src.index < info.numArgs) { // arg - val offset = 4 * src.index - offsets.put(src, offset) - buf += new Mips.NativeLoadWord(dst, Mips.SP, offset) - return - } - throw new IllegalArgumentException("offsets doesn't contain " + src + " when loading " + dst) + var isArgOrLocal = true + if (src.index < info.numArgs) { // arg + if (!offsets.contains(src)) { + val offset = 4 * src.index + offsets.put(src, offset) + buf += new Mips.NativeLoadWord(dst, Mips.SP, offset, true) + return + } + isArgOrLocal = true + } + else { + if (!offsets.contains(src)) { + throw new IllegalArgumentException("offsets doesn't contain " + src + " when loading " + dst) + } + isArgOrLocal = false } - buf += new Mips.NativeLoadWord(dst, Mips.SP, offsets(src)) + buf += new Mips.NativeLoadWord(dst, Mips.SP, offsets(src), isArgOrLocal) + } + + override def emitCall(argsNum: Int): Unit = { + maxArgsNum = maxArgsNum max argsNum } override def emitMove(dst: Reg, src: Reg): Unit = { @@ -71,25 +88,39 @@ class MipsSubroutineEmitter private[mips](emitter: MipsAsmEmitter, info: Subrout } override def emitEnd(used: Set[Reg]): Unit = { + maxArgsSize = maxArgsNum * 4; + frameLength = nextLocalOffset + maxArgsSize + printer.printComment("start of prologue") - printer.printInstr(new Mips.SPAdd(-nextLocalOffset), "push stack frame") + printer.printInstr(new Mips.SPAdd(-frameLength), "push stack frame") if (info.hasCalls) { - printer.printInstr(new Mips.NativeStoreWord(Mips.RA, Mips.SP, info.argsSize + 36), "save the return address") + // 40 whitespaces for 10 saved reg ($s0 ~ $s8), + // where in common mips implementation there's only 9 regs. + printer.printInstr(new Mips.NativeStoreWord(Mips.RA, Mips.SP, maxArgsSize + 40), "save the return address") } for { (reg, i) <- Mips.calleeSaved.zipWithIndex if used(reg) } { - printer.printInstr(new Mips.NativeStoreWord(reg, Mips.SP, info.argsSize + 4 * i), "save value of " + reg) + printer.printInstr(new Mips.NativeStoreWord(reg, Mips.SP, maxArgsSize + 4 * i), "save value of " + reg) } printer.printComment("end of prologue") printer.println() printer.printComment("start of body") for (i <- 0 until Math.min(info.numArgs, 4)) { - printer.printInstr(new Mips.NativeStoreWord(Mips.argRegs(i), Mips.SP, 4 * i), "save arg " + i) + printer.printInstr(new Mips.NativeStoreWord(Mips.argRegs(i), Mips.SP, frameLength + 4 * i), "save arg " + i) } - buf.foreach(printer.printInstr) + buf.foreach( + instr => { + instr match { + case nlw: Mips.NativeLoadWord => nlw.backfill(maxArgsNum, frameLength); + case nsw: Mips.NativeStoreWord => nsw.backfill(maxArgsNum, frameLength); + case _ => + } + printer.printInstr(instr) + } + ) printer.printComment("end of body") printer.println() @@ -99,13 +130,13 @@ class MipsSubroutineEmitter private[mips](emitter: MipsAsmEmitter, info: Subrout (reg, i) <- Mips.calleeSaved.zipWithIndex if used(reg) } { - printer.printInstr(new Mips.NativeLoadWord(Mips.calleeSaved(i), Mips.SP, info.argsSize + 4 * i), + printer.printInstr(new Mips.NativeLoadWord(Mips.calleeSaved(i), Mips.SP, maxArgsSize + 4 * i), "restore value of $S" + i) } if (info.hasCalls) { - printer.printInstr(new Mips.NativeLoadWord(Mips.RA, Mips.SP, info.argsSize + 36), "restore the return address") + printer.printInstr(new Mips.NativeLoadWord(Mips.RA, Mips.SP, maxArgsSize + 40), "restore the return address") } - printer.printInstr(new Mips.SPAdd(nextLocalOffset), "pop stack frame") + printer.printInstr(new Mips.SPAdd(frameLength), "pop stack frame") printer.printComment("end of epilogue") printer.println() @@ -114,7 +145,13 @@ class MipsSubroutineEmitter private[mips](emitter: MipsAsmEmitter, info: Subrout } private val buf = new mutable.ArrayBuffer[NativeInstr] - private var nextLocalOffset = info.argsSize + 40 + private var maxArgsNum = 4; + private var maxArgsSize = 4 * 4; + private var nextLocalOffset = 44 + private var frameLength = 0 + + // The offset of parameters are negative, + // as the length of the frame is not known at the native instructions are emitted. private val offsets = new mutable.TreeMap[Temp, Integer] printer.printLabel(info.funcLabel, "function " + info.funcLabel.prettyString) diff --git a/src/main/scala/decaf/backend/reg/BruteRegAlloc.scala b/src/main/scala/decaf/backend/reg/BruteRegAlloc.scala index 9f77fa0..bba0cbe 100644 --- a/src/main/scala/decaf/backend/reg/BruteRegAlloc.scala +++ b/src/main/scala/decaf/backend/reg/BruteRegAlloc.scala @@ -3,6 +3,7 @@ package decaf.backend.reg import decaf.backend.asm.{AsmEmitter, Holes, SubroutineEmitter, SubroutineInfo} import decaf.backend.dataflow._ import decaf.lowlevel.instr.{PseudoInstr, Reg, Temp} +import decaf.lowlevel.tac.TacInstr.{IndirectCall, DirectCall} import scala.collection.mutable import scala.util.Random @@ -91,6 +92,12 @@ final class BruteRegAlloc(emitter: AsmEmitter) extends RegAlloc(emitter) { // For normal instructions: allocate registers for every read/written temp. Skip the already specified // special registers. + case loc if loc.instr.isInstanceOf[IndirectCall] => + ctx.subEmitter.emitCall(loc.instr.asInstanceOf[IndirectCall].numArgs); + + case loc if loc.instr.isInstanceOf[DirectCall] => + ctx.subEmitter.emitCall(loc.instr.asInstanceOf[DirectCall].numArgs); + case loc => allocForLoc(loc) } From dd36d3982db214f3c0cd522611990b66c666d3cf Mon Sep 17 00:00:00 2001 From: TA Date: Mon, 13 Jan 2020 19:23:46 +0800 Subject: [PATCH 3/3] Correct the dealing with local data. --- src/main/java/decaf/lowlevel/Mips.java | 22 ++++++++----------- .../asm/mips/MipsSubroutineEmitter.scala | 4 ++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/main/java/decaf/lowlevel/Mips.java b/src/main/java/decaf/lowlevel/Mips.java index 5edf4a7..579d965 100644 --- a/src/main/java/decaf/lowlevel/Mips.java +++ b/src/main/java/decaf/lowlevel/Mips.java @@ -301,12 +301,8 @@ public NativeLoadWord(Reg dst, Reg base, int offset, boolean isArgOrLocal) { private boolean isArgOrLocal; // [true] represents argument, and [false] represents local data. - public void backfill(int maxArgsNum, int frameLength) { - if (isArgOrLocal) { - offset += frameLength; - } else { - offset += Math.max(maxArgsNum - 4, 0) * 4; - } + public void backfill(int maxArgsSize, int frameLength) { + offset += isArgOrLocal ? frameLength : maxArgsSize; } private int offset; @@ -330,14 +326,14 @@ public NativeStoreWord(Reg src, Reg base, int offset, boolean isArgOrLocal) { this.isArgOrLocal = isArgOrLocal; } - private boolean isArgOrLocal; + private boolean isArgOrLocal; // [true] represents argument, and [false] represents local data. + + public void backfill(int maxArgsSize, int frameLength) { + offset += isArgOrLocal ? frameLength : maxArgsSize; - public void backfill(int maxArgsNum, int frameLength) { - if (isArgOrLocal) { - offset += frameLength; - } else { - offset += Math.max(maxArgsNum - 4, 0) * 4; - } + // System.out.println("After backfill(maxArgsSize = " + maxArgsSize + ", + // frameLength = " + frameLength + // + "), offset = " + offset + "\n"); } private int offset; diff --git a/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala b/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala index 71cac33..2130aa8 100644 --- a/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala +++ b/src/main/scala/decaf/backend/asm/mips/MipsSubroutineEmitter.scala @@ -114,8 +114,8 @@ class MipsSubroutineEmitter private[mips](emitter: MipsAsmEmitter, info: Subrout buf.foreach( instr => { instr match { - case nlw: Mips.NativeLoadWord => nlw.backfill(maxArgsNum, frameLength); - case nsw: Mips.NativeStoreWord => nsw.backfill(maxArgsNum, frameLength); + case nlw: Mips.NativeLoadWord => nlw.backfill(maxArgsSize, frameLength); + case nsw: Mips.NativeStoreWord => nsw.backfill(maxArgsSize, frameLength); case _ => } printer.printInstr(instr)