def c_gen_code_get_array_pointer(self): '''Creates code that will store the array a reference to the array in ebx and the offset for the index in eax.''' array_check_pass = manager.CodeGenManager.get_label('array_check_pass') array_check_fail = manager.CodeGenManager.get_label('array_check_fail') # Assume that we're doing an array read. return [ self.array_expression.c_gen_code(), common.check_null('eax'), 'push eax', self.index.c_gen_code(), 'pop ebx ; restore the pointer to the array', common.unwrap_primitive('eax', 'eax'), '; check whether the index is out of bounds:', common.get_array_length('ecx', 'ebx'), common.unwrap_primitive('ecx', 'ecx'), 'cmp eax, ecx', 'jge {0}'.format(array_check_fail), 'cmp eax, 0', 'jl {0}'.format(array_check_fail), 'jmp {0}'.format(array_check_pass), '{0}:'.format(array_check_fail), 'call __exception', '{0}:'.format(array_check_pass), '; calculate the offset into the array:', 'imul eax, 4', 'add eax, 12', ]
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): from ast_expression import ASTLiteral if self.type_node.is_primitive and not self.type_node.is_array: primitive_sizes = { 'boolean': 0x1, 'byte': 0xff, 'char': 0xff, 'int': 0xffffffff, 'null': 0x0, 'short': 0xffff, } expr_size = primitive_sizes[str(self.expressions[0].expr_type)] result_size = primitive_sizes[str(self.type_node)] # Widen all numeric types but chars. widen_code = [] if str(self.expressions[0].expr_type) in ['byte', 'short']: done_label = CodeGenManager.get_label('cast_widen_done') if expr_size == 0xff: widen_code = [ 'mov ebx, eax', 'and ebx, 0x80', 'cmp ebx, 0x80', 'jne {0}'.format(done_label), 'or eax, 0xffffff00', '{0}:'.format(done_label), ] elif expr_size == 0xffff: widen_code = [ 'mov ebx, eax', 'and ebx, 0x8000', 'cmp ebx, 0x8000', 'jne {0}'.format(done_label), 'or eax, 0xffff0000', '{0}:'.format(done_label), ] return [ self.expressions[0].c_gen_code(), common.unwrap_primitive('eax', 'eax'), widen_code, 'and eax, {0} ; narrow to {1}'.format(result_size, str(self.type_node)), 'push eax ; create new primitive with value', 'call _create_int', 'pop ebx ; pop param', ] else: subtype_offset = 4 * CodeGenManager.get_subtype_table_index( self.type_node) finished_label = CodeGenManager.get_label('cast_exp_finished') return [ self.expressions[0].c_gen_code(), # Null check. 'mov ebx, 0', 'cmp eax, ebx', 'je {0}'.format(finished_label), common.unwrap_subtype_col_from_object('ebx', 'eax'), 'mov ebx, [ebx + {0}]'.format(subtype_offset), 'mov ecx, 1', 'cmp ebx, ecx', 'je {0}'.format(finished_label), '; OH NO! CastException!', 'call __exception', '{0}:'.format(finished_label), ]