def _spill(self, pseudo_register, physical_register):
        """ A private method for handling the logic for spilling the contents of a physical register into memory.

        Since this method is used as a callback, it cannot return things in the traditional sense. Because of this, the
        "returned" code and physical register are set to two private class variables, so the programmer must take care
        to manage these variables appropriately.

        :param pseudo_register: The name of the pseudo-register to be spilled. Aka 'key' for the purposes of the
                                pylru.lrucache callback.
        :physical_register: The name of the physical register to be freed/reused. Aka 'value' for the purposes of the
                                pylru.lrucache callback.
        :return: None.
        """

        self._spill_code = []
        self._freed_physical_register = physical_register

        if not self.available_spill_memory_words:
            print(self)
            raise OutOfSpillMemoryException()

        spill_offset = self.available_spill_memory_words.pop()

        self.spilled_registers[pseudo_register] = spill_offset

        self._spill_code = [
            mi.COMMENT("spilling psuedo-register {} to free {}".format(pseudo_register, physical_register)),
            mi.SW(physical_register, mi.offset_label_immediate(self.spill_mem_base_label, spill_offset)),
            mi.COMMENT("spill complete")
        ]
    def _recover(self, pseudo_register):
        """ Handles the logic for reversing the spilling of a register.

        :param pseudo_register: The name of the pseudo-register whose spilled value is being recovered.
        :return: A tuple containing the physical register and a list of the MIPS code required to free the physical
                 register for use.
        """

        spill_offset = self.spilled_registers.pop(pseudo_register)
        physical_register = None
        code = [
            mi.COMMENT("recovering pseudo-register {}".format(pseudo_register))
        ]

        if self.available_registers:
            physical_register = self.available_registers.pop()
            self.lru_cache[pseudo_register] = physical_register

        else:
            self.lru_cache[pseudo_register] = None
            physical_register = self._freed_physical_register

            code.extend(self._spill_code)

            self.lru_cache[pseudo_register] = physical_register

            code.append(
                mi.LW(physical_register, mi.offset_label_immediate(self.spill_mem_base_label, spill_offset)))

        self.available_spill_memory_words.append(spill_offset)

        return physical_register, code
Ejemplo n.º 3
0
__print_char_return_type = symbol.TypeDeclaration()
__print_char_return_type.add_type_specifier('int')

__print_char_parameter = symbol.VariableSymbol('x', 0, 0)
__print_char_parameter_type = symbol.TypeDeclaration()
__print_char_parameter_type.add_type_specifier('int')
__print_char_parameter.add_type_declaration(__print_char_parameter_type)

PrintCharDeclaration = symbol.FunctionSymbol('print_char', 0, 0)
PrintCharDeclaration.set_named_parameters([__print_char_parameter])
PrintCharDeclaration.add_return_type_declaration(__print_char_return_type)

__print_char_body = [
    mm.CALLEE_FUNCTION_PROLOGUE_MACRO.call('0'),
    mi.COMMENT("load $v0 with the value for the print char syscall"),
    mi.LI(mr.V0, __PRINT_CHAR_SYSCALL),
    mi.COMMENT("the first (and only) argument is the value to print"),
    mi.LW(mr.A0, mi.offset_from_register_with_immediate(mr.FP)),
    mi.SYSCALL(),
    mm.CALLEE_FUNCTION_EPILOGUE_MACRO.call()
]
PrintCharDefinition = FunctionDefinition(identifier='print_char',
                                         body=__print_char_body)

#
# PRINT INTEGER
#
__PRINT_INT_SYSCALL = 1

__print_int_return_type = symbol.TypeDeclaration()
Ejemplo n.º 4
0
 def _comment(self, t):
     self.mips_output.append(mi.COMMENT(text=t.dest))
Ejemplo n.º 5
0
        self.args = args if args else []
        self.body = body if body else []

    def definition(self):
        return [mi.BEGIN_MACRO(self.name, self.args)
                ] + self.body + [mi.END_MACRO()]

    def call(self, *args):
        return mi.CALL_MACRO(self.name, args)


__T_REGISTERS = (mr.T0, mr.T1, mr.T2, mr.T3, mr.T4, mr.T5, mr.T6, mr.T7, mr.T8,
                 mr.T9)

__save_register_macro_instructions = [
    mi.COMMENT("brace yourself for a long, unrolled loop...")
]
for __temp_register in __T_REGISTERS:
    __save_register_macro_instructions.append(
        mi.SW(__temp_register, mi.offset_from_register_with_immediate(mr.SP)))
    __save_register_macro_instructions.append(
        mi.SUBIU(mr.SP, mr.SP, mr.WORD_SIZE))
if config.NOT_TESTING_FUNCTIONS:
    __save_register_macro_instructions = []
SAVE_REGISTER_MACRO = Macro(name='SAVE_T_REGISTERS',
                            args=None,
                            body=__save_register_macro_instructions)

__restore_register_macro_instructions = [
    mi.COMMENT("brace yourself for a long, unrolled loop...")
]