def c_gen_code(self): import code_gen.asm.common as common CodeGenManager.N_PARAMS = self.c_num_params CodeGenManager.cur_method = self body_code = [] if self.body: body_code = self.body.c_gen_code() constructor_code = [] # Each constructor does the three tasks: # 1. Call parent constructor (if one exists). # 2. Set field values. # 3. Run constructor body. if self.is_constructor: parent_code = [] if self.parent_type.canonical_name != 'java.lang.Object': super_class = self.parent_type.super[0].definition super_sig = (str(super_class.name), []) super_constructor, _ = super_class.environment.lookup_method(super_sig, constructor=True) parent_code = [ common.get_param('eax', 0, self.c_num_params), 'push eax', 'call {0}'.format(super_constructor.c_defn_label), 'pop ebx ; pop to garbage', ] field_init_code = [] for f in self.parent_type.fields: if f.is_static: continue field_init_code.append([ '; setting value for field {0}'.format(str(f.identifier)), 'push eax ; save |this|', code_gen.asm.object.create_starting_value(f), 'mov ebx, eax ; move result to ebx', 'pop eax ; restore |this|', common.save_instance_field('eax', f, 'ebx'), ]) constructor_code = [ parent_code, field_init_code, ] ret = [ 'global {0}'.format(self.c_defn_label), '{0}:'.format(self.c_defn_label), common.function_prologue(self.c_num_local_vars * 4), constructor_code, body_code, common.function_epilogue(), ] CodeGenManager.N_PARAMS = 0 CodeGenManager.cur_method = None return ret
def c_gen_code_create_instance(self): '''Creates an instance of this class in memory and does all prep work so that the constructor can be called. Precisely, does the following: 1. Allocate memory for the object. 2. Sets a pointer to the CIT on the instance. 3. Initializes all fields to their default value. The following should be done by the ClassInstanceCreation: 1. Call the parent constructor. 2. Initialize fields declared on the class. 3. Run constructor body.''' import code_gen.asm.common as common import code_gen.asm.object as object_ field_init_code = [] for f in self.get_all_fields(): type_node = f.type_node field_init_code.extend([ 'push eax ; save |this|', object_.create_default_value(type_node.is_primitive, type_node.is_array), 'mov ebx, eax ; store result in ebx', 'pop eax ; restore |this|', common.save_instance_field('eax', f, 'ebx'), ]) return [ 'global {0}'.format(self.c_create_object_function_label), '{0}:'.format(self.c_create_object_function_label), common.malloc(self.c_object_size), # Class info table 'mov dword [eax], {0}'.format(self.c_cit_label), field_init_code, 'ret', ]
def c_gen_code(self): import code_gen.access as access result = self.right.c_gen_code() # The left hand side is either an ASTArrayAccess, ASTFieldAccess or # ASTIdentifiers. if isinstance(self.left, ASTIdentifiers): # For assignment expressions, we evaluate the left hand side first. If # the left hand side is an ASTIdentifiers, the same ASTIdentifiers could # be used on the right hand side in an assignment. # Thus, we must store a reference to where the left hand side points # before evaluating the right hand side. if self.left.is_simple: # If the left hand side is simple, it is either a method parameter, # local variable or an instance field on the enclosing type. The # location for all of these cannot be altered by the right hand side, # so we can calculate the right hand side first. return [ result, access.set_simple_var(self.left.simple_decl, 'eax'), ] else: import code_gen.annotate_ids as annotate_ids annotations = annotate_ids.annotate_identifier(self.left) if len(annotations) == 0: # If we do not have any annotations then the left hand side is a # static field. This address cannot change. return [ result, access.set_simple_static_field(self.left, 'eax'), ] else: # _get_to_final provides code to store a pointer to the second last # part of the identifier in $eax. type_, code = access._get_to_final(self.left, annotations) env = type_.definition.environment final_part = str(self.left.parts[-1]) f, _ = env.lookup_field(final_part) return [ code, common.check_null('eax'), 'push eax ; save instance that we want to store a field on', result, 'pop ebx ; instance to store a field on', common.save_instance_field('ebx', f, 'eax'), ] elif isinstance(self.left, ASTFieldAccess): left_asm = self.left.left.c_gen_code() left_t = self.left.left.expr_type if left_t.is_array: raise Exception('Trying to write to array field') return [ '; FieldAccess assignment', access.get_field_from_parts( left_t, self.left.right, left_asm, get_addr=True), 'push eax ; Save field addr', result, '; RHS of assignment should be eax', 'pop ebx ; Pop addr of field', 'mov [ebx], eax ; Assign!' ] elif isinstance(self.left, ASTArrayAccess): array_soundness_pass = manager.CodeGenManager.get_label('array_soundness_pass') soundness_asm = [] if not self.left.array_expression.expr_type.is_primitive: soundness_asm = [ 'push eax', 'push ebx', 'push ecx', '; Get CIT of right side', 'mov ecx, [ecx]' '; Get subtype col of right side', 'mov ecx, [ecx + 4]', '; get subtype offset', 'mov ebx, [ebx + 4]', '; index into subtype col', 'mov ecx, [ecx + ebx]', 'cmp ecx, 1 ; 1 means that RHS is a subtype of LHS', 'je {0}'.format(array_soundness_pass), 'call __exception', '{0}:'.format(array_soundness_pass), 'pop ecx', 'pop ebx', 'pop eax', ] # The result is calculated after the array index offset. return [ self.left.c_gen_code_get_array_pointer(), 'push ebx ; save array pointer', 'push eax ; save array offset', result, 'mov ecx, eax ; move result', 'pop eax ; restore array offset', 'pop ebx ; restore array pointer', '; do array type soundness check', soundness_asm, 'mov [ebx + eax], ecx', 'mov eax, ecx ; result should be in eax', ] raise Exception('Programmer error: trying to assign to invalid AST')