Exemplo n.º 1
0
class IrvmFrame(Frame):
    """Frame for an ARM function."""

    # Word size for the target architecture.
    word_size = 4

    param_regs = [Temp("i%d" % i) for i in range(4)]

    # Predefined registers used at many places.
    rv = Temp("rv")
    sp = Temp("sp")
    fp = Temp("fp")

    # List of callee save registers.
    callee_save = []

    # List of caller save registers.
    # caller_save = list(Temp("i%d" % i) for i in range(0, 4))
    caller_save = []

    def __init__(self, label):
        super().__init__(label)
        self.end_label = Label("end")

    def wrap_result(self, sxp):
        super().wrap_result(sxp)
        return MOVE(TEMP(self.rv), sxp)

    def label_name(self, suffix):
        return "L%s" % suffix

    def allocate_frame_size(self):
        return MOVE(TEMP(self.sp), BINOP('-', TEMP(self.sp),
                                         CONST(self.offset)))
Exemplo n.º 2
0
class ArmFrame(Frame):
    """Frame for an ARM function."""

    # Word size for the target architecture.
    word_size = 4

    param_regs = [Temp("r0"), Temp("r1"), Temp("r2"), Temp("r3")]

    # Predefined registers used at many places.
    r0 = Temp("r0")
    lr = Temp("lr")
    sp = Temp("sp")
    fp = Temp("r11")

    # List of callee save registers.

    callee_save = list(Temp("r%d" % i) for i in range(4, 11))

    # List of caller save registers.
    caller_save = list(Temp("r%d" % i) for i in range(0, 4))

    def __init__(self, label):
        super().__init__(label)

    def wrap_result(self, sxp):
        super().wrap_result(sxp)
        return MOVE(TEMP(self.r0), sxp)
Exemplo n.º 3
0
    def decorate(self, stm):
        """Decorate the `stm` with code which sets up the frame, the stack
        pointer, the registers holding the parameters, the preservation of
        the callee saved registers, and the end label."""

        # Begin and end label creation
        begin_label = [LABEL(self.label)]
        end_label = [LABEL(self.end_label)]

        # If we are in the main function, we do not need to save or restore
        # anything.
        if self.label.name == 'main':
            return SEQ(begin_label + [stm] + end_label)

        # Code to save and restore the previous frame pointer and set-it up
        # wrt the stack pointer. Also, a label is put at the place where the
        # frame size will be allocated later (we will only know this
        # information once all the code has been generated and physical
        # registers have been allocated).
        saved_fp = Temp.create("savedfp")
        save_fp = [
            MOVE(TEMP(saved_fp), TEMP(self.fp)),
            MOVE(TEMP(self.fp), TEMP(self.sp)),
            self.allocate_frame_size()
        ]
        restore_fp = [
            MOVE(TEMP(self.sp), TEMP(self.fp)),
            MOVE(TEMP(self.fp), TEMP(saved_fp))
        ]

        # Code to save the static link register into the frame at offset 0.
        save_static_link = [MOVE(MEM(TEMP(self.fp)), TEMP(self.param_regs[0]))]

        # Code to save and restore the callee-save registers.
        callee_save_map = dict(
            (reg, Temp.create("callee_save")) for reg in self.callee_save)
        save_callee_save = [
            MOVE(TEMP(callee_save_map[reg]), TEMP(reg))
            for reg in self.callee_save
        ]
        restore_callee_save = [
            MOVE(TEMP(reg), TEMP(callee_save_map[reg]))
            for reg in reversed(self.callee_save)
        ]

        # Code to transfer the parameters from registers or call stack into the
        # register or the frame position they belong to (according to their
        # Access parameter). The first parameter (r0, in which the static link
        # had been written) has already been handled above.
        store_parameters = \
            [MOVE(access.toSxp(self.fp),
                  TEMP(self.param_regs[idx + 1])
                  if idx < self.max_params_in_regs - 1
                  else InFrame((idx - self.max_params_in_regs + 1) *
                               self.word_size).toSxp(self.fp))
             for (idx, access) in enumerate(self.param_access)]

        return SEQ(begin_label + save_fp + save_static_link +
                   save_callee_save + store_parameters + [stm] +
                   restore_callee_save + restore_fp + end_label)
Exemplo n.º 4
0
 def prologue(self):
     save_callee_save, restore_callee_save = self.preserve_callee_save()
     lr_temp = Temp.create("lr_save")
     save_lr, restore_lr = MOVE(TEMP(lr_temp), TEMP(self.lr)), \
                           MOVE(TEMP(self.lr), TEMP(lr_temp))
     store_parameters = self.transfer_parameters()
     # The fp save and static link will be saved while generating the code
     # with ARM specific instructions.
     return [LABEL(self.label)] + self.allocate_frame_size() + \
            [save_lr] + save_callee_save + store_parameters, \
            restore_callee_save + [restore_lr]
Exemplo n.º 5
0
class IrvmFrame(Frame):
    """Frame for a function."""

    # Word size for the target architecture.
    word_size = 4

    # Infinite number of parameter registers in IRVM. 128 is close
    # enough to infinity, right?
    param_regs = [Temp("i%d" % i) for i in range(128)]

    # Predefined registers used at many places.
    rv = Temp("rv")
    sp = Temp("sp")
    fp = Temp("fp")

    # List of callee save registers.
    callee_save = []

    # List of caller save registers.
    # caller_save = list(Temp("i%d" % i) for i in range(0, 4))
    caller_save = []

    def __init__(self, label):
        super().__init__(label)
        self.end_label = Label("end")

    def wrap_result(self, sxp):
        super().wrap_result(sxp)
        return MOVE(TEMP(self.rv), sxp)

    def label_name(self, suffix):
        return "L%s" % suffix

    def allocate_frame_size(self):
        """In IRVM, we know the frame size at this stage already since
        we have an infinite number of registers and thus no spills."""
        return [MOVE(TEMP(self.sp),
                     BINOP('+', TEMP(self.sp), CONST(-self.offset)))] \
               if self.offset else []
Exemplo n.º 6
0
 def preserve_callee_save(self):
     """Save all the callee save registers and return
     a list of move instructions to save them and a list
     of move instructions to restore them."""
     callee_save_map = dict(
         (reg, Temp.create("callee_save")) for reg in self.callee_save)
     save_callee_save = [
         MOVE(TEMP(callee_save_map[reg]), TEMP(reg))
         for reg in self.callee_save
     ]
     restore_callee_save = [
         MOVE(TEMP(reg), TEMP(callee_save_map[reg]))
         for reg in reversed(self.callee_save)
     ]
     return save_callee_save, restore_callee_save
Exemplo n.º 7
0
 def __init__(self, prefix=None):
     self.temp = TEMP(Temp.create(prefix))
Exemplo n.º 8
0
class ArmFrame(Frame):
    """Frame for an ARM function."""

    # Word size for the target architecture.
    word_size = 4

    param_regs = [Temp("r0"), Temp("r1"), Temp("r2"), Temp("r3")]

    # Predefined registers used at many places.
    r0 = Temp("r0")
    lr = Temp("lr")
    sp = Temp("sp")
    fp = Temp("r11")

    # List of callee save registers (the frame pointer is handled separately).
    callee_save = list(Temp("r%d" % i) for i in range(4, 11))

    # List of caller save registers.
    caller_save = list(Temp("r%d" % i) for i in range(4)) + [lr]

    # All physical registers appearing in code, used for register allocation.
    registers = list(Temp("r%d" % i) for i in range(11)) + [sp, lr, fp]

    def __init__(self, label):
        super().__init__(label)

    def wrap_result(self, sxp):
        super().wrap_result(sxp)
        return MOVE(TEMP(self.r0), sxp)

    def prologue(self):
        save_callee_save, restore_callee_save = self.preserve_callee_save()
        lr_temp = Temp.create("lr_save")
        save_lr, restore_lr = MOVE(TEMP(lr_temp), TEMP(self.lr)), \
                              MOVE(TEMP(self.lr), TEMP(lr_temp))
        store_parameters = self.transfer_parameters()
        # The fp save and static link will be saved while generating the code
        # with ARM specific instructions.
        return [LABEL(self.label)] + self.allocate_frame_size() + \
               [save_lr] + save_callee_save + store_parameters, \
               restore_callee_save + [restore_lr]

    def epilogue(self, data):
        return [LABEL(self.restore_label)] + data + [LABEL(self.end_label)]

    def load_spill(self, temp, offset):
        assert isinstance(temp, Temp)
        assert isinstance(offset, int)
        return [
            O("ldr {{}}, [{{}}, #{:d}]".format(offset),
              dsts=[temp],
              srcs=[self.fp])
        ]

    def save_spill(self, temp, offset):
        assert isinstance(temp, Temp)
        assert isinstance(offset, int)
        return [
            O("str {{}}, [{{}}, #{:d}]".format(offset), srcs=[temp, self.fp])
        ]

    def reserve_stack_space(self):
        return [O("add {{}}, {{}}, #-{}".format(self.offset), dsts=[self.sp], srcs=[self.sp])] \
                if self.offset else []