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}