def emit_assign_to(self, src, context): out = '' type = context.get_type(self.type_name) offset = type.get_field_offset(self.field_name) basecalc, base_dest = self.base.emit_with_dest(context) out += basecalc loc = None if offset == 0: loc = base_dest elif offset == 4: loc = base_dest.with_flag(asm.DataFlag.PLUSFOUR) else: out += asm.Instruction(asm.Opcode.ADD, [ base_dest, asm.DataLoc(asm.LocType.CONST, asm.ConstWord(offset)), TEMPSTACK ]).emit() loc = TEMPSTACK out += asm.Instruction(asm.Opcode.MOVE, [src, loc.with_flag(asm.DataFlag.MEM)]).emit() return out
def emit_with_dest(self, context): type = context.get_type(self.type_name) if type is None: raise Exception("Type {} does not exist in context {}".format( self.type_name, context)) offset = type.get_field_offset(self.field_name) out = '' basecalc, base_dest = self.base.emit_with_dest(context) out += basecalc loc = None if offset == 0: loc = base_dest elif offset == 4: loc = base_dest.with_flag(asm.DataFlag.PLUSFOUR) else: out += asm.Instruction(asm.Opcode.ADD, [ base_dest, asm.DataLoc(asm.LocType.CONST, asm.ConstWord(offset)), TEMPSTACK ]).emit() loc = TEMPSTACK #out += asm.Instruction(asm.Opcode.ADD, [base_dest, asm.DataLoc(asm.LocType.CONST, asm.ConstWord(offset)), TEMPSTACK]).emit() return (out, loc.with_flag(asm.DataFlag.MEM))
def emit_with_dest(self, context): argcalcs = [] dests = [] for arg in self.args: calc, dest = arg.emit_with_dest(context) argcalcs.append(calc) dests.append(dest) # If the function returns a value, it's going to have to be cleared off of the # function result stack one way or another. try: has_result = context.does_fn_return_value(self.fname) except SymbolNotRegisteredException: # We don't know about this function, we'll just have to assume the user knows best. # The safe default is to not cause a stack underflow. has_result = False if has_result: result_dest = RESULT_STACK else: result_dest = ZERO_WORD func_loc = context.get_loc_for_name(self.fname) call = asm.Instruction(asm.Opcode.FUNCCALL, [func_loc] + dests) return (''.join(argcalcs) + call.emit(), result_dest)
def emit(self, context): out = '' calc, dest = self.expr.emit_with_dest(context) out += calc if self.expr.must_read_result(context): # out += asm.Instruction(asm.Opcode.MOVE, [dest, asm.DataLoc(asm.LocType.CONST, asm.ConstWord(0))]).emit() out += asm.Instruction(asm.Opcode.READ, [dest]).emit() return out
def emit_jump_true(self, dest, context): out = '' if type(self.b) is ConstExpr and self.b.has_value(0): acalc, adest = self.a.emit_with_dest(context) out += acalc out += asm.Instruction(asm.Opcode.JUMPZERO, [adest, dest]).emit() return out elif type(self.b) is ConstExpr and self.b.has_value('ZZZZ'): acalc, adest = self.a.emit_with_dest(context) out += acalc out += asm.Instruction( asm.Opcode.JUMPZERO, [adest.with_flag(asm.DataFlag.NEG), dest]).emit() return out else: return super().emit_jump_true(dest, context)
def emit_jump_false(self, jump_dest, context): out = '' calc, calc_dest = self.emit_with_dest(context) out += calc out += asm.Instruction(asm.Opcode.JUMPZERO, [calc_dest, jump_dest]).emit() return out
def emit_jump_true(self, jump_dest, context): '''Emits code that jumps to a location if the expr is truthy.''' out = '' calc, calc_dest = self.emit_with_dest(context) out += calc out += asm.Instruction(asm.Opcode.JUMPGREATER, [calc_dest, ZERO_WORD, jump_dest]).emit() return out
def emit_with_dest(self, context): out = '' equal_label = asm.AnonLabel('equal') equaldone_label = asm.AnonLabel('equal_done') acalc, adest = self.a.emit_with_dest(context) bcalc, bdest = self.b.emit_with_dest(context) out += asm.comment("Begin equality check") out += bcalc # Eval B out += acalc # Eval A out += self.emit_conditional(adest, bdest, equal_label.as_dataloc()) out += asm.Instruction(asm.Opcode.MOVE, [ZERO_WORD, TEMPSTACK]).emit() out += asm.Jump(equaldone_label.as_dataloc()).emit() out += equal_label.emit() out += asm.Instruction(asm.Opcode.MOVE, [MAX_WORD, TEMPSTACK]).emit() out += equaldone_label.emit() out += asm.comment("End equality check") return (out, TEMPSTACK)
def emit(self, context): if self.expr: out = '' calc, dest = self.expr.emit_with_dest(context) out += calc # If the calc dest is already the return stack, # it's really just a waste of time to move it. if dest == RESULT_STACK: out += asm.comment("Omitting return move") else: out += asm.Instruction(asm.Opcode.MOVE, [dest, RESULT_STACK]).emit() out += asm.Jump(RETURN_LOC).emit() return out else: return asm.Jump(RETURN_LOC).emit()
def emit(self, context): if 'returns' in self.options: context.register_fn(self.name, True) else: context.register_fn(self.name, False) c = Context(parent=context, name="Function {}".format(self.name)) move_args = '' # Args are pushed backwards for arg in reversed(self.args): c.make_var(arg) reg = c.get_loc_for_name(arg) move_args += asm.Instruction(asm.Opcode.MOVE, [ARGSTACK, reg]).emit() inner = move_args + self.sequence.emit(c) to_preserve = c.get_used_regs() context.inherit(c) return asm.Function(self.name, inner, preserving=to_preserve).emit()
def emit_assign_to(self, src, context): return asm.Instruction( asm.Opcode.MOVE, [src, asm.DataLoc(asm.LocType.TAPE, asm.ConstWord(self.letter)) ]).emit()
def emit_assign_to(self, src, context): return asm.Instruction(asm.Opcode.MOVE, [src, asm.DataLoc(asm.LocType.IO)]).emit()
def emit_assign_to(self, src, context): assert type(src) is asm.DataLoc loccalc, locto = self.loc.emit_with_dest(context) refloc = locto.with_flag(asm.DataFlag.MEM) return loccalc + asm.Instruction(asm.Opcode.MOVE, [src, refloc]).emit()
def emit_conditional(self, aloc, bloc, successloc): return asm.Instruction(asm.Opcode.AND, [aloc, bloc, successloc]).emit()
def emit_with_dest(self, context): acalc, adest = self.a.emit_with_dest(context) bcalc, bdest = self.b.emit_with_dest(context) ins = asm.Instruction(self.opcode(), [adest, bdest, TEMPSTACK]) return ("{}{}{}".format(acalc, bcalc, ins.emit()), TEMPSTACK)
def emit(self, context): return asm.Instruction(asm.Opcode.NOP).emit()
def emit_assign_to(self, src, context): assert type(src) is asm.DataLoc var_reg = context.get_reg_for_var(self.name) return asm.Instruction( asm.Opcode.MOVE, [src, context.get_loc_for_name(self.name)]).emit()