def gen_method(info, method_obj): node = method_obj.node assert node.name in 'MethodDeclaration' # Preprocessing: # Assign frame pointer offsets to each parameter and local variable # declaration node. param_start_index = len(node.find_child('Parameters').children) + 1 for decl in node.find_child('Parameters').children: decl.frame_offset = param_start_index param_start_index -= 1 local_var_start_index = -1 num_vars = 0 all_local_decls = list(node.select(['LocalVariableDeclaration'])) for decl in all_local_decls: decl.frame_offset = local_var_start_index local_var_start_index -= 1 num_vars += 1 output = [] # Preamble for method. output.append(method_obj.node.label + ':') # save ebp & esp output.extend([ "push ebp", "mov ebp, esp", ]) # make room for local vars in the stack output.append("sub esp, %d" % (num_vars*4)) body = node[4] # MethodBody if len(body.children) != 0: output.extend(statement.gen_block(info, body[0], method_obj)) # restore ebp & esp output.extend([ "END~%s:" % (method_obj.node.label), "mov esp, ebp", "pop ebp", "ret" ]) return output
def gen_constructor(info, constructor_obj): node = constructor_obj.node assert node.name == 'ConstructorDeclaration' # Preprocessing: # Assign frame pointer offsets to each parameter and local variable # declaration node. param_start_index = len(node.find_child('Parameters').children) + 1 for decl in node.find_child('Parameters').children: decl.frame_offset = param_start_index param_start_index -= 1 local_var_start_index = -1 num_vars = 0 all_local_decls = list(node.select(['LocalVariableDeclaration'])) for decl in all_local_decls: decl.frame_offset = local_var_start_index local_var_start_index -= 1 num_vars += 1 output = [] # Preamble for constructor. output.append(constructor_obj.node.label + ':') # save ebp & esp output.extend([ "push ebp", "mov ebp, esp", ]) # make room for local vars in the stack output.append("sub esp, %d" % (num_vars*4)) # Call superclass default constructor if this is not java.lang.Object. if info.class_obj.name != 'java.lang.Object': this_offset = (len(constructor_obj.params) * 4) + 8 output.append('mov eax, %d' % this_offset) output.append('mov eax, [eax+ebp]') output.append('push eax') superclass = info.class_obj.extends.name superclass_simple = superclass.split('.')[-1] superclass_label = 'CONSTRUCTOR~%s.%s~' % (superclass, superclass_simple) output.append('call %s' % superclass_label) output.append('add esp, 4') # Initialize instance fields. for member in info.class_obj.declare: if isinstance(member, class_hierarchy.Field) == False: continue field_obj = member field_node = field_obj.node if 'Static' not in field_obj.mods and \ len(field_node[3].children) == 1: # Initializer # Evaluate initializer. output.extend(expression.gen_expr(info, field_node[3][0], constructor_obj)) # Get the address of 'this'. this_offset = (len(constructor_obj.params) * 4) + 8 output.append('mov ebx, ebp') output.append('add ebx, %d' % this_offset) output.append('mov ebx, [ebx]') # Assign to field offset. receiver_type = info.class_obj.name field_name = field_obj.name field_offset = info.get_field_offset_from_field_name(receiver_type, field_name) field_offset += 12 output.append('mov [ebx+%d], eax' % field_offset) body = node # ConstructorBody if len(body.children) != 0: output.extend(statement.gen_block(info, body[3], constructor_obj)) # restore ebp & esp output.extend([ "END~%s:" % (constructor_obj.node.label), "mov esp, ebp", "pop ebp", "ret" ]) return output