def c_gen_code(self): '''Generate method invocation code''' import code_gen.invoke as invoke import code_gen.annotate_ids as annotate_ids # Get the ASM to push the arguments on the stack left to right. args_asm = invoke.get_arg_list(self.arguments) # Simple case: The method invocation is just off an ASTIdentifiers. if self.right is None: ids = self.left if len(ids.parts) == 1: # Method invocation off implcit "this". Joos does not allow static # methods to be called with an implcit type. code = [ '; Put "this" in eax before calling implicit this method', common.get_param('eax', 0, manager.CodeGenManager.N_PARAMS) ] this_type = manager.CodeGenManager.cur_method.parent_type return invoke.call_method_with_final( this_type, ids, code, self.arg_types, args_asm) annotation = annotate_ids.annotate_identifier(ids) if len(annotation) == 0: # Call a static method m, since we have handled the implcit "this" # case above. return invoke.call_static_method(ids, self.arg_types, args_asm) return invoke.call_simple_method(ids, self.arg_types, args_asm) # If we have a right side, then the left side should be evaluated and # the method should be taken off that side. left_asm = self.left.c_gen_code() left_t = self.left.expr_type return invoke.call_method_parts( left_t, self.right, left_asm, self.arg_types, args_asm)
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 create_array(is_primitive, array_cit_label, subtype_offset = 0): ''' Returns code for a function that creates an array in memory. This function does NOT include a label, because each reference/primitive type will need their own version of this function. You should put your own label above this code. Structure of the created array object is as follows: 1. Pointer to Array CIT 2. The type's subtype column offset for reference types, 0 for primitives 3. Length (reference to a integer) 4. Array elements 1 Param: The length of the array (a reference to an integer)''' N_PARAMS = 1 # The first 12 bytes are for the pointer to the Array CIT, the subtype column # offset, and the length. Remaining bytes are for the array elements # (4 bytes each) array_length_pass = CodeGenManager.get_label('array_length_pass') return [ common.function_prologue(), common.get_param('ebx', 0, N_PARAMS), common.unwrap_primitive('ebx', 'ebx'), '; ebx now contains the length of the array', '; check that array length is not negative:', 'cmp ebx, 0', 'jge {0}'.format(array_length_pass), 'call __exception', '{0}:'.format(array_length_pass), 'push ebx ; store the array length (# elems)', '; calculate how much memory to allocate, based on length of array:', 'imul ebx, 4 ; 4 bytes for every element', 'add ebx, 12 ; add an extra 12 bytes for pointers/length field', common.malloc_reg('ebx'), 'pop ebx ; restore length (# elems)', 'mov edx, eax ; save pointer to array memory in edx', 'push eax', '; set array elems to their default values:', _array_init_loop(is_primitive), '; create an int to store the length of the array:', 'push ebx;', 'call _create_int', 'pop ecx; pop param to garbage', 'mov ebx, eax ; ebx has pointer to integer representing array length', 'pop eax ; eax now has pointer to memory from malloc call', 'mov dword [eax], {0}'.format(array_cit_label), 'mov dword [eax + 4], {0}'.format(subtype_offset*4), 'mov dword [eax + 8], ebx', common.function_epilogue() ]
def c_gen_code(self): return [ common.get_param('eax', 0, manager.CodeGenManager.N_PARAMS) ]