Add TP04a
This commit is contained in:
parent
b7601abd73
commit
4c7a2c85a2
@ -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
|
||||
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user