Beispiel #1
0
    def to_3ac(self, get_rval=True, include_source=False):
        output = [tac.SOURCE(self.lineno, self.column)]

        # Get ticket to copy memory location
        if type_utils.is_floating_point_type(self.get_resulting_type()):
            value = tickets.FLOAT_REGISTER_TICKETS.get()
        else:
            value = tickets.INT_REGISTER_TICKETS.get()

        if get_rval:
            # load the register with the variable's value

            if self.immutable:
                output.append(tac.LI(value, taci.Immediate(self.value)))

            if self.global_memory_location:
                address = taci.Address(label=self.global_memory_location)

            else:
                address = taci.Address(
                    int_literal=-self.activation_frame_offset,
                    register=tacr.FP)

            output.append(tac.LOAD(value, address, self.size_in_bytes()))

            return {'3ac': output, 'rvalue': value}

        else:
            if self.immutable:
                raise Exception(
                    'Immutable symbols should not provide lvalues.')

            # load the register with the address of the variable
            if self.global_memory_location:
                output.append(
                    tac.LA(value,
                           taci.Address(label=self.global_memory_location)))

            else:
                # remember, stack grows downward, so look under the FP

                # LA is probably better for readability than the SUB instruction, but I'm leaving it around in
                # case a bug crops up
                output.append(
                    tac.LA(
                        value,
                        taci.Address(int_literal=-self.activation_frame_offset,
                                     register=tacr.FP)))
                # output.append(tac.SUB(value, taci.Register(tacr.FP), self.activation_frame_offset))

                # output.append(tac.ADD(value, taci.Register(tacr.FP), self.activation_frame_offset))
                # pass

            return {'3ac': output, 'lvalue': value}
    def to_3ac(self, get_rval=False, include_source=False):
        output = [SOURCE(self.linerange[0], self.linerange[1])]

        # Get memory location of expression by calling to3ac function
        result = (self.expression.to_3ac(get_rval=False))
        if '3ac' in result:
            output.extend(result['3ac'])
        lvalue = result['lvalue']

        # Get the rvalue
        rvalue = tickets.INT_REGISTER_TICKETS.get()
        output.append(LOAD(rvalue, taci.Address(register=lvalue), WORD_SIZE))

        # if this is a post-increment, copy the register with the current value of the register so we can return that
        # before the plusplus happens
        if not self.pre:

            # Copy the contents of the rvalue before the operator is applied
            # It will be returned while the actual variable is updated
            rvalue_copy = tickets.INT_REGISTER_TICKETS.get()
            output.append(ADD(rvalue_copy, rvalue, taci.Register(tacr.ZERO)))

            # Determine correct operator and apply to register
            if self.operator == '++':
                output.append(ADDIU(rvalue, rvalue, 1))
            if self.operator == '--':
                output.append(SUBI(rvalue, rvalue, 1))

            # Store updated value and kick the lvalue & rvalue
            output.append(
                STORE(rvalue, taci.Address(register=lvalue), WORD_SIZE))
            output.append(KICK(lvalue))
            output.append(KICK(rvalue))

            return {'3ac': output, 'rvalue': rvalue_copy}

        else:

            # Determine correct operator and apply to register
            if self.operator == '++':
                output.append(ADDIU(rvalue, rvalue, 1))
            if self.operator == '--':
                output.append(SUBI(rvalue, rvalue, 1))

            # Store updated value and kick the lvalue
            output.append(
                STORE(rvalue, taci.Address(register=lvalue), WORD_SIZE))
            output.append(KICK(lvalue))

            return {'3ac': output, 'rvalue': rvalue}
    def to_3ac(self, get_rval=True, include_source=False):
        _3ac = [SOURCE(self.linerange[0], self.linerange[1])]

        # Get memory address of lvalue by calling to3ac on lvalue
        left = self.lvalue.to_3ac(get_rval=False)
        lval = left['lvalue']
        if '3ac' in left:
            _3ac.extend(left['3ac'])

        # Get rvalue by calling to3ac on rvalue
        right = self.rvalue.to_3ac(get_rval=True)
        rval = right['rvalue']
        if '3ac' in right:
            _3ac.extend(right['3ac'])

        # Store the rvalue at the lvalue address
        _3ac.append(
            STORE(taci.Register(rval), taci.Address(register=lval),
                  self.lvalue.size_in_bytes()))
        _3ac.append(KICK(lval))

        return {'3ac': _3ac, 'rvalue': rval}
    def to_3ac(self, get_rval=True, include_source=False):
        _3ac = [SOURCE(self.linerange[0], self.linerange[1])]
        dim_count = len(self.symbol.array_dims)

        if dim_count is 0:
            raise Exception(
                'There was an error. Subscripting a non-array symbol.')

        # Initialize offset_reg to the value of the first subscript
        subscript_tac = self.subscripts[0].to_3ac(get_rval=True)
        if '3ac' in subscript_tac:
            _3ac.extend(subscript_tac['3ac'])

        # The first subscript is the initial value for the subscript
        offset_reg = subscript_tac['rvalue']

        # range(a,b) is [inclusive, exclusive)
        for i in range(0, dim_count - 1):
            if self.symbol.is_parameter:

                # Allocate a new ticket to get the address offset from FP
                dimension_reg = tickets.INT_REGISTER_TICKETS.get()
                _3ac.append(
                    LOAD(
                        dimension_reg,
                        taci.Address(
                            int_literal=-(self.symbol.activation_frame_offset +
                                          8 + (4 * (i + 1))),
                            register=tacr.FP), WORD_SIZE))
                _3ac.append(MUL(offset_reg, offset_reg, dimension_reg))
                _3ac.append(KICK(dimension_reg))

            else:
                _3ac.append(
                    MUL(offset_reg, offset_reg, self.symbol.array_dims[i + 1]))

            # Add the 3AC to load the subscript
            subscript_tac = self.subscripts[i + 1].to_3ac(get_rval=True)
            if '3ac' in subscript_tac:
                _3ac.extend(subscript_tac['3ac'])

            # Add the subscript to the offset
            _3ac.append(ADDU(offset_reg, offset_reg, subscript_tac['rvalue']))

            # Kick the temporary
            _3ac.append(KICK(subscript_tac['rvalue']))

        # Offset by symbol size
        _3ac.append(MUL(offset_reg, offset_reg, self.symbol.size_in_bytes()))

        # Allocate two new registers
        base_address_reg = tickets.INT_REGISTER_TICKETS.get()
        end_address_reg = tickets.INT_REGISTER_TICKETS.get()

        # Check bounds
        if self.symbol.is_parameter:

            _3ac.append(
                LOAD(
                    base_address_reg,
                    taci.Address(
                        int_literal=-(self.symbol.activation_frame_offset),
                        register=tacr.FP), WORD_SIZE))
            _3ac.append(
                LOAD(
                    end_address_reg,
                    taci.Address(
                        int_literal=-(self.symbol.activation_frame_offset +
                                      WORD_SIZE),
                        register=tacr.FP), WORD_SIZE))
            _3ac.append(SUB(end_address_reg, base_address_reg,
                            end_address_reg))
            _3ac.append(SUB(offset_reg, base_address_reg, offset_reg))

            # Check base_address_reg >= offset_reg > end_address_reg (because upside-down stack)
            _3ac.append(BOUND(offset_reg, base_address_reg, end_address_reg))

        else:

            # Compute the size in bytes for the entire array
            array_size_in_bytes = self.symbol.array_size * self.symbol.size_in_bytes(
            )

            if self.symbol.global_memory_location:

                _3ac.append(
                    LI(base_address_reg, self.symbol.global_memory_location))
                _3ac.append(
                    LI(
                        end_address_reg, self.symbol.global_memory_location -
                        array_size_in_bytes))
                # TODO This doesn't look right. Global is a 154235345 type number right?
                _3ac.append(
                    SUB(offset_reg, self.symbol.global_memory_location,
                        offset_reg))

            else:
                _3ac.append(
                    LA(
                        base_address_reg,
                        taci.Address(
                            int_literal=-(self.symbol.activation_frame_offset),
                            register=tacr.FP)))
                _3ac.append(
                    ADDI(end_address_reg, base_address_reg,
                         -array_size_in_bytes))
                _3ac.append(SUB(offset_reg, base_address_reg, offset_reg))

            # Check base_address_reg >= offset_reg > end_address_reg (because upside-down stack)
            _3ac.append(BOUND(offset_reg, base_address_reg, end_address_reg))

        # Kick the temporaries
        _3ac.append(KICK(base_address_reg))
        _3ac.append(KICK(end_address_reg))

        # Return the appropriate dict
        if get_rval:
            _3ac.append(
                LOAD(offset_reg, taci.Address(register=offset_reg),
                     self.symbol.size_in_bytes()))
            return {'3ac': _3ac, 'rvalue': offset_reg}
        else:
            return {'3ac': _3ac, 'lvalue': offset_reg}
    def to_3ac(self, get_rval=True, include_source=False):
        _3ac = []
        return_type = self.function_symbol.get_resulting_type()

        if type_utils.is_floating_point_type(return_type):
            rvalue = tickets.FLOAT_REGISTER_TICKETS.get()
        else:
            rvalue = tickets.INT_REGISTER_TICKETS.get()

        # Call the prologue macro
        _3ac.append(
            CALL_PROC(self.function_symbol.identifier,
                      self.function_symbol.activation_frame_size))

        # Copy the argument values into
        for parameter_template, argument in itertools.zip_longest(
                self.function_symbol.named_parameters, self.arguments):
            # evaluate the argument expression
            # get register with value of arg
            arg_result = argument.to_3ac(get_rval=True)
            _3ac.extend(arg_result['3ac'])
            arg_rvalue = arg_result['rvalue']

            arg_type = type_utils.INT if arg_rvalue[
                0] == 'i' else type_utils.FLOAT
            param_type = type_utils.INT if type_utils.is_integral_type(
                return_type) else type_utils.FLOAT

            # Get casted value if necessary
            if arg_type != param_type:
                if type_utils.is_integral_type(param_type):
                    new_register = tickets.INT_REGISTER_TICKETS.get()
                    _3ac.append(CVTSW(new_register, arg_rvalue))
                    _3ac.append(KICK(arg_rvalue))
                    arg_rvalue = new_register
                else:
                    new_register = tickets.FLOAT_REGISTER_TICKETS.get()
                    _3ac.append(CVTWS(new_register, arg_rvalue))
                    _3ac.append(KICK(arg_rvalue))
                    arg_rvalue = new_register

            # store value at memory location indicated by parameter_template
            # offset = parameter_template.activation_frame_offset
            #  ^
            # likely unnecessary since we are moving the stack pointer as we push arguments
            # if a bug crops up, be sure to check this out
            offset = 0

            if isinstance(argument, VariableSymbol) and argument.is_array:
                # Kick the old register in case it was a float register
                _3ac.append(KICK(arg_rvalue))

                # Get a new integer register
                arg_rvalue = tickets.INT_REGISTER_TICKETS.get()
                _3ac.append(
                    LA(
                        arg_rvalue,
                        taci.Address(int_literal=-parameter_template.
                                     activation_frame_offset,
                                     register=tacr.FP)))

                # Store the base address
                _3ac.append(
                    STORE(arg_rvalue,
                          taci.Address(int_literal=offset, register=tacr.SP),
                          WORD_SIZE))
                _3ac.append(
                    SUB(taci.Register(tacr.SP), taci.Register(tacr.SP),
                        WORD_SIZE))

                # Store the total array size
                _3ac.append(
                    LI(arg_rvalue,
                       argument.size_in_bytes() * argument.array_size))
                _3ac.append(
                    STORE(arg_rvalue,
                          taci.Address(int_literal=offset, register=tacr.SP),
                          WORD_SIZE))
                _3ac.append(
                    SUB(taci.Register(tacr.SP), taci.Register(tacr.SP),
                        WORD_SIZE))

                # Store the size of each dimension
                for dim in argument.array_dims:
                    _3ac.append(LI(arg_rvalue, dim))
                    _3ac.append(
                        STORE(
                            arg_rvalue,
                            taci.Address(int_literal=offset, register=tacr.SP),
                            WORD_SIZE))
                    _3ac.append(
                        SUB(taci.Register(tacr.SP), taci.Register(tacr.SP),
                            WORD_SIZE))

            else:
                # Store the value and move the stack pointer
                _3ac.append(
                    STORE(arg_rvalue,
                          taci.Address(int_literal=offset, register=tacr.SP),
                          WORD_SIZE))
                _3ac.append(
                    SUB(taci.Register(tacr.SP), taci.Register(tacr.SP),
                        WORD_SIZE))

            # Kick out the temporary at the end of the argument iterating loop
            _3ac.append(KICK(arg_rvalue))

        # Jump to function body
        _3ac.append(JAL(self.function_symbol.identifier))

        # The function will jump back to this address at this point

        # Call the epilogue macro
        _3ac.append(CORP_LLAC(self.function_symbol.activation_frame_size))

        # Copy the return value before it gets obliterated
        _3ac.append(
            ADD(rvalue, taci.Register(tacr.RV), taci.Register(tacr.ZERO)))

        # TODO: handle double word returns if we get there
        return {'3ac': _3ac, 'rvalue': rvalue}
    def to_3ac(self, include_source=False):
        _3ac = [SOURCE(self.linerange[0], self.linerange[1])]

        if self.initializer is None:
            return {'3ac': _3ac}

        if self.symbol.global_memory_location:
            if self.initializer:
                if not self.initializer.immutable:
                    raise Exception(
                        'Initializers to global objects must be constants.')

                _3ac.append(
                    GLOBLDECL(self.symbol.global_memory_location, WORD_SPEC,
                              self.initializer.value))

            else:
                _3ac.append(
                    GLOBLDECL(self.symbol.global_memory_location, WORD_SPEC))

            return {'3ac': _3ac}

        # Get a register that points to the variable's memory so we can initialize it
        lvalue = tickets.INT_REGISTER_TICKETS.get()
        if self.symbol.global_memory_location:
            base_address = self.symbol.global_memory_location
            _3ac.append(LI(lvalue, base_address))
        else:
            # Remember, stacks grow down, so go below FP
            _3ac.append(
                LA(
                    lvalue,
                    taci.Address(
                        int_literal=-self.symbol.activation_frame_offset,
                        register=tacr.FP)))

        # If the initializer is a list (for arrays)
        if isinstance(self.initializer, list):

            # Loop through initializer and store
            self.initializer = self.initializer[:min(len(
                self.initializer), self.symbol.array_dims[0])]
            for item in self.initializer:

                # Load the value
                item_tac = item.to_3ac(get_rval=True)
                if '3ac' in item_tac:
                    _3ac.extend(item_tac['3ac'])

                # Store the value into memory, kick the register, and move to next
                _3ac.append(
                    STORE(item_tac['rvalue'], taci.Address(register=lvalue),
                          self.symbol.size_in_bytes()))

                # Kick the temporaries
                if 'rvalue' in item_tac:
                    _3ac.append(KICK(item_tac['rvalue']))
                if 'lvalue' in item_tac:
                    _3ac.append(KICK(item_tac['lvalue']))

                # Go to the next index / offset by subtracting one element size
                _3ac.append(ADDI(lvalue, lvalue, -self.symbol.size_in_bytes()))

        else:

            # Load the value
            item_tac = self.initializer.to_3ac(get_rval=True)
            if '3ac' in item_tac:
                _3ac.extend(item_tac['3ac'])

            # Store the value into memory, kick the register,
            _3ac.append(
                STORE(item_tac['rvalue'], taci.Address(register=lvalue),
                      self.symbol.size_in_bytes()))

            # Kick the temporaries
            if 'rvalue' in item_tac:
                _3ac.append(KICK(item_tac['rvalue']))
            if 'lvalue' in item_tac:
                _3ac.append(KICK(item_tac['lvalue']))

        # Kick the base address
        _3ac.append(KICK(lvalue))
        return {'3ac': _3ac}