def gen_array_access_addr(info, node, method_obj): assert node.name == 'ArrayAccess' output = ['; BEGIN gen_array_access_addr'] # Generate receiver code. output.extend(gen_expr(info, node[0][0], method_obj)) # Make sure the array we're indexing into is not null. output.extend(util.gen_null_check()) output.append('push eax') # Generate index code into ebx. output.extend(gen_expr(info, node[1], method_obj)) output.append('mov ebx, eax') # eax has array. output.append('pop eax') # Check that index is within array bounds. output.extend(util.gen_array_bounds_check()) # Skip SIT pointer and length field. # Note: java.lang.Object has no fields. output.append('add ebx, 4') output.append('shl ebx, 2') # Multiply index (offset) by 4. output.append('add eax, ebx') # Address is at array addr + offset. output.append('; END gen_array_access_addr') return output
def gen_ambiguous_name(info, node, method_obj): output = ["; START gen_ambiguous_name"] output.extend(gen_ambiguous_name_addr(info, node, method_obj)) output.extend(util.gen_null_check()) output.append('mov eax, [eax]') output.append('; END gen_ambiguous_name') return output
def gen_field_access_addr(info, node, method_obj): output = [] # Gets the field receiver. obj_output = gen_expr(info, node.find_child("FieldReceiver")[0], method_obj) output.extend(obj_output) output.extend(util.gen_null_check()) if typecheck.is_array_type(node[1][0].typ) == True: # Array output.append('add eax, %d' % 12) else: # Object. offset = info.get_field_offset(node) output.append("add eax, %i" % (12 + offset)) return output
def gen_method_invocation(info, node, method_obj): receiver = node.find_child("MethodReceiver") if len(receiver.children) != 0 and receiver[0].typ == None: return gen_static_method_invocation(info, node, method_obj) output = ["; START gen_method_invocation for %s" % node.decl.label] # get addr of method receiver output.append("; Eval receiver") obj_output = None if len(receiver.children) != 0: obj_output = gen_expr(info, receiver[0], method_obj) else: obj_output = gen_this(info, None, method_obj) output.extend(obj_output) output.extend(util.gen_null_check()) output.append("push eax") # calculate args, push args; left-to-right args = list(node.find_child("Arguments").children) num_args = len(args) output.append("; Eval %i args" % num_args) for arg in args: output.extend(gen_expr(info, arg, method_obj)) output.append("push eax") # Get the label corresponding to the method, using the SIT. output.append("; Get method impl") offset = info.get_method_offset(node) output.append("mov eax, [esp + %i] ; addr of receiver" % (num_args*4)) output.append("mov eax, [eax] ; SIT") output.append("mov eax, [eax + %i] ; addr of method" % (offset)) output.append("call eax") # pop obj addr and args output.append("add esp, %i ; pop this and args" % (4 + num_args*4)) output.append("; END gen_method_invocation") return output
def gen_ambiguous_name_addr(info, node, method_obj): assert node.name == 'Name' output = ['; gen_ambiguous_name_addr'] # Loop through each identifier node, looking for a significant node. significant_node = None significant_index = -1 for i, id_node in enumerate(node.children): if hasattr(id_node, 'decl') or hasattr(id_node, 'canon'): significant_node = id_node significant_index = i break assert significant_index != -1 # Did not find anything, error. # We have Type.something, so there must be a next node. # This is a Static field access. id_node = significant_node i = significant_index prev_type = None if hasattr(id_node, 'canon') and id_node.canon != None: assert (i + 1) < len(node.children) # Return address of static field. next_node = node[i + 1].decl # decl should be static field ASTNode assert next_node.name == 'FieldDeclaration' assert 'static' in next_node.modifiers output.append('mov eax, %s' % next_node.label) i += 2 # Processed 2 nodes. prev_type = next_node[1].canon # Get type from Type node # We have local_var.something. Move its addr to eax. elif id_node.decl.name == 'LocalVariableDeclaration': assert i == 0 # Local variable must be first identifier. # Get the offset from the frame pointer. output.append('mov eax, ebp') local_var_offset = id_node.decl.frame_offset * 4 output.append('add eax, %d' % local_var_offset) i += 1 prev_type = id_node.decl[0].canon # Get type from Type node # We have a parameter.something. Move its addr to eax. elif id_node.decl.name == 'Parameter': assert i == 0 # Parameter must be first identifier. # Get the offset from the frame pointer. output.append('mov eax, ebp') param_offset = (id_node.decl.frame_offset * 4) output.append('add eax, %d' % param_offset) i += 1 prev_type = id_node.decl[0].canon # Get type from Type node # We have an implicit 'this' on an instance field. elif id_node.decl.name == 'FieldDeclaration': assert i == 0 # Field declaration must be first identifier. # Get this into eax. output.extend(gen_this(info, None, method_obj)) # If the field type is array, we must get the array field. offset = 0 receiver_type = info.class_obj.name field_name = id_node.decl.obj.name offset = info.get_field_offset_from_field_name(receiver_type, field_name) offset += 12 prev_type = id_node.decl[1].canon # Generic type. # Load the field address offset. output.append('add eax, %d' % offset) i += 1 # All the remaining things are instance fields. We have the address in eax # already, so we just keep going. while i < len(node.children): assert i >= 1 assert prev_type != None field_node = node[i] assert field_node.decl.name in ['FieldDeclaration', 'FakeFieldDeclaration'] # Nullcheck and dereference the previous result into eax. output.extend(util.gen_null_check()) output.append('mov eax, [eax]') # Calculate the offset of the field. offset = 0 # Array; length has type Int. if typecheck.is_array_type(prev_type): assert i == (len(node.children) - 1) # Must be last element. offset = 12 prev_type = 'Int' # Object. Must search up the object's type (in prev_type) in the field # index and get the offset. else: prev_type_field_list = info.field_index[prev_type] field_name = field_node.decl.obj.name temp = class_hierarchy.Temp_Field(field_name) offset = (prev_type_field_list.index(temp) * 4) + 12 # Keep the type. prev_type = field_node.decl[1].canon output.append('add eax, %d' % offset) i += 1 output.append('; end of gen_ambiguous_name_addr') return output