Exemple #1
0
  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)
Exemple #2
0
  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
Exemple #3
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()
  ]
Exemple #4
0
 def c_gen_code(self):
   return [
     common.get_param('eax', 0, manager.CodeGenManager.N_PARAMS)
   ]