Exemplo n.º 1
0
  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',
    ]
Exemplo n.º 2
0
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()
  ]
Exemplo n.º 3
0
  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),
      ]