diff --git a/MiniC/TP04/AllInMemAllocator.py b/MiniC/TP04/AllInMemAllocator.py index 6c24403..7e73a27 100644 --- a/MiniC/TP04/AllInMemAllocator.py +++ b/MiniC/TP04/AllInMemAllocator.py @@ -14,11 +14,23 @@ class AllInMemAllocator(Allocator): before: List[Instruction] = [] after: List[Instruction] = [] new_args: List[Operand] = [] - # TODO: compute before,after,args. - # TODO: iterate over old_args, check which argument - # TODO: is a temporary (e.g. isinstance(..., Temporary)), - # TODO: and if so, generate ld/sd accordingly. Replace the - # TODO: temporary with S[1], S[2] or S[3] physical registers. + + s_index = 0 + for arg in old_instr.args(): + if isinstance(arg, Temporary): + # TODO: don't ld/sd when nothing changed (eg don't ld a destination only, + # TODO: don't sd a source only) + s_index += 1 + before.append(RiscV.ld( + S[s_index], arg.get_alloced_loc() + )) + after.append(RiscV.sd( + S[s_index], arg.get_alloced_loc() + )) + new_args.append(S[s_index]) + else: + new_args.append(arg) + new_instr = old_instr.with_args(new_args) return before + [new_instr] + after diff --git a/MiniC/TP04/MiniCCodeGen3AVisitor.py b/MiniC/TP04/MiniCCodeGen3AVisitor.py index 6098a19..e211d90 100644 --- a/MiniC/TP04/MiniCCodeGen3AVisitor.py +++ b/MiniC/TP04/MiniCCodeGen3AVisitor.py @@ -74,8 +74,13 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): raise MiniCUnsupportedError("float literal") def visitBooleanAtom(self, ctx) -> Operands.Temporary: - # true is 1 false is 0 - raise NotImplementedError() # TODO + dest = self._current_function.fdata.fresh_tmp() + self._current_function.add_instruction( + RiscV.li( + dest, Operands.Immediate(1 if ctx.getText() == "true" else 0) + ) + ) + return dest # true is 1 false is 0 def visitIdAtom(self, ctx) -> Operands.Temporary: try: @@ -99,13 +104,37 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): assert ctx.myop is not None tmpl: Operands.Temporary = self.visit(ctx.expr(0)) tmpr: Operands.Temporary = self.visit(ctx.expr(1)) - raise NotImplementedError() # TODO + tmp = self._current_function.fdata.fresh_tmp() + + if ctx.myop.type == MiniCParser.PLUS: + self._current_function.add_instruction( + RiscV.add(tmp, tmpl, tmpr) + ) + elif ctx.myop.type == MiniCParser.MINUS: + self._current_function.add_instruction( + RiscV.sub(tmp, tmpl, tmpr) + ) + else: + raise MiniCInternalError( + f"Unknown additive operator '{ctx.myop}'") + + return tmp def visitOrExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError() # TODO + tmp = self._current_function.fdata.fresh_tmp() + t1, t2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1)) + self._current_function.add_instruction( + RiscV.lor(tmp, t1, t2) + ) + return tmp def visitAndExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError() # TODO + tmp = self._current_function.fdata.fresh_tmp() + t1, t2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1)) + self._current_function.add_instruction( + RiscV.land(tmp, t1, t2) + ) + return tmp def visitEqualityExpr(self, ctx) -> Operands.Temporary: return self.visitRelationalExpr(ctx) @@ -117,18 +146,83 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): print("relational expression:") print(Trees.toStringTree(ctx, [], self._parser)) print("Condition:", c) - raise NotImplementedError() # TODO + + dest = self._current_function.fdata.fresh_tmp() + t1 = self.visit(ctx.expr(0)) + t2 = self.visit(ctx.expr(1)) + + endrel = self._current_function.fdata.fresh_label("end_rel") + + # dest <- 1 + # t1 cond t2 ? jmp end + # dest <- 0 + # end: + self._current_function.add_instruction( + RiscV.li(dest, Operands.Immediate(1))) + + self._current_function.add_instruction( + RiscV.conditional_jump(endrel, t1, Condition(ctx.myop.type), t2)) + self._current_function.add_instruction( + RiscV.li(dest, Operands.Immediate(0))) + + self._current_function.add_label(endrel) + return dest def visitMultiplicativeExpr(self, ctx) -> Operands.Temporary: assert ctx.myop is not None div_by_zero_lbl = self._current_function.fdata.get_label_div_by_zero() - raise NotImplementedError() # TODO + t1 = self.visit(ctx.expr(0)) + t2 = self.visit(ctx.expr(1)) + dest = self._current_function.fdata.fresh_tmp() + + if ctx.myop.type == MiniCParser.DIV or ctx.myop.type == MiniCParser.MOD: + self._current_function.add_instruction( + RiscV.conditional_jump(div_by_zero_lbl, t2, Condition("beq"), Operands.ZERO)) + + if ctx.myop.type == MiniCParser.MULT: + self._current_function.add_instruction( + RiscV.mul(dest, t1, t2)) + elif ctx.myop.type == MiniCParser.DIV: + self._current_function.add_instruction( + RiscV.div(dest, t1, t2)) + elif ctx.myop.type == MiniCParser.MOD: + self._current_function.add_instruction( + RiscV.rem(dest, t1, t2)) + else: + raise MiniCInternalError( + f"Unknown additive operator '{ctx.myop}'") + + return dest def visitNotExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError() # TODO + dest = self._current_function.fdata.fresh_tmp() + label_neq_zero = self._current_function.fdata.fresh_label("neq_zero") + t1 = self.visit(ctx.expr()) + + # dest <- 0 + # t1 != dest ? jmp neq_zero + # dest <- 1 + # neq_zero: + self._current_function.add_instruction( + RiscV.li(dest, Operands.Immediate(0)) + ) + self._current_function.add_instruction( + RiscV.conditional_jump(label_neq_zero, t1, Condition("bne"), Operands.ZERO) + ) + self._current_function.add_instruction( + RiscV.li(dest, Operands.Immediate(1)) + ) + + self._current_function.add_label(label_neq_zero) + return dest def visitUnaryMinusExpr(self, ctx) -> Operands.Temporary: - raise NotImplementedError("unaryminusexpr") # TODO + dest = self._current_function.fdata.fresh_tmp() + + self._current_function.add_instruction( + RiscV.sub(dest, Operands.ZERO, self.visit(ctx.expr())) + ) + return dest def visitProgRule(self, ctx) -> None: self.visitChildren(ctx) @@ -160,8 +254,25 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): def visitIfStat(self, ctx) -> None: if self._debug: print("if statement") + else_label = self._current_function.fdata.fresh_label("else_if") end_if_label = self._current_function.fdata.fresh_label("end_if") - raise NotImplementedError() # TODO + + self._current_function.add_instruction( + RiscV.conditional_jump( + else_label, self.visit(ctx.expr()), + Condition('beq'), Operands.ZERO + ) + ) + + self.visit(ctx.stat_block()[0]) + self._current_function.add_instruction( + RiscV.jump(end_if_label) + ) + + self._current_function.add_label(else_label) + if len(ctx.stat_block()) > 1: + self.visit(ctx.stat_block()[1]) + self._current_function.add_label(end_if_label) def visitWhileStat(self, ctx) -> None: @@ -170,7 +281,31 @@ class MiniCCodeGen3AVisitor(MiniCVisitor): print(Trees.toStringTree(ctx.expr(), [], self._parser)) print("and block is:") print(Trees.toStringTree(ctx.stat_block(), [], self._parser)) - raise NotImplementedError() # TODO + + # ltest <- fresh_label() + loop_test = self._current_function.fdata.fresh_label("loop_test") + # lendwhile <- fresh_label() + end_while = self._current_function.fdata.fresh_label("end_while") + # code.addLabel(ltest) + self._current_function.add_label(loop_test) + # t1 <- GenCodeExpr(b) + # code.add("beq lendwhile, t1, 0") + + self._current_function.add_instruction( + RiscV.conditional_jump( + end_while, self.visit(ctx.expr()), + Condition('beq'), Operands.ZERO + ) + ) + # GenCodeSmt(S) # execute S + self.visit(ctx.stat_block()) + # code.add("j ltest") # and jump to the test + self._current_function.add_instruction( + RiscV.jump(loop_test) + ) + # code.addLabel(lendwhile) # else it is done. + self._current_function.add_label(end_while) + # visit statements def visitPrintlnintStat(self, ctx) -> None: