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