예제 #1
0
    def prologue(self):
        """Return the function prologue and some opaque value
        which will be passed to the epilogue. It can be used to
        pass a register map to be restored from the epilogue for
        example.

        In this generic method, we will pass around a list of
        move instructions needed to restore the callee-save
        registers and the frame pointer.

        It is expected that specific frames will generate more
        specialized prologues, using dedicated instructions
        such as push and pop that cannot be easily represented
        using the IR."""

        begin_label = LABEL(self.label)

        # Push the previous frame pointer and the static link to the stack
        # and setup the new frame pointer.
        save_fp = [MOVE(TEMP(self.sp),
                        BINOP("+", TEMP(self.sp), CONST(-self.word_size))),
                   MOVE(MEM(TEMP(self.sp)),
                        TEMP(self.fp)),
                   MOVE(TEMP(self.sp),
                       BINOP("+", TEMP(self.sp), CONST(-self.word_size))),
                    MOVE(MEM(TEMP(self.sp)),
                        TEMP(self.param_regs[0])),
                    MOVE(TEMP(self.fp), TEMP(self.sp))] + \
                    self.allocate_frame_size()
        restore_fp = [
            MOVE(TEMP(self.sp), BINOP("+", TEMP(self.fp),
                                      CONST(self.word_size))),
            MOVE(TEMP(self.fp), MEM(TEMP(self.sp))),
            MOVE(TEMP(self.sp), BINOP("+", TEMP(self.sp),
                                      CONST(self.word_size)))
        ]

        # Code to save and restore the callee-save registers.
        save_callee_save, restore_callee_save = self.preserve_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 = self.transfer_parameters()

        return [begin_label] + save_fp + save_callee_save + \
               store_parameters, restore_callee_save + restore_fp
예제 #2
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)
예제 #3
0
 def toSxp(self, fp):
     return MEM(BINOP('+', fp, CONST(self.offset)))
예제 #4
0
 def one_frame_up(self, current_fp):
     """Return the frame pointer one frame above this one. fp is an Sxp
     with the current frame pointer, return value is a MEM expression
     with the frame pointer one level up."""
     assert isinstance(current_fp, Sxp), "fp must be an expression"
     return MEM(current_fp)