Example #1
0
  def c_gen_code(self):
    before_expr_label = CodeGenManager.get_label('for_loop_expr')
    done_for_label = CodeGenManager.get_label('for_loop_done')

    init_code = []
    if self.init is not None:
      init_code = self.init.c_gen_code()

    expr_code = []
    if self.expression is not None:
      expr_code = common.if_false(self.expression, done_for_label)

    update_code = []
    if self.update is not None:
      update_code = self.update.c_gen_code()

    body_code = []
    if self.statement is not None:
      body_code = self.statement.c_gen_code()

    return [
      '; for loop',
      '; init code',
      init_code,
      '; expression',
      '{0}:'.format(before_expr_label),
      expr_code,
      '; body: ',
      body_code,
      '; update',
      update_code,
      'jmp {0}'.format(before_expr_label),
      '{0}:'.format(done_for_label),
    ]
Example #2
0
def _get_field_defns(t):
  '''Return stoarge locations for each of the static fields.
  Static fields are stored in the data segment with code.'''
  ret = []
  for f in t.fields:
    if f.is_static:
      CodeGenManager.add_global_label(t.canonical_name, f.c_defn_label)
      ret.append([
        'global {0}'.format(f.c_defn_label),
        '{0}: ; Static field {1}'.format(f.c_defn_label, f.identifier),
        'dd 0x0',
      ])
  return ret
Example #3
0
def _array_init_loop(is_primitive):
  ''' Code that loops through array elements to initialize them.
  This code does not save/restore registers, it should only be called from
  create_array() '''

  # Code that will create the default value for a single array element:
  default_value_code = asm_object.create_default_value(is_primitive, False)

  loop_start, loop_end = CodeGenManager.get_labels(
    'array_init_loop_start', 'array_init_loop_end')

  # eax gets set to the an element'ss default value
  # ebx stores the length of the array (number of elements)
  # ecx is the loop counter
  # edx is a pointer to the start of the array
  return [
    'mov ecx, 0  ; ecx is counter for which array index we\'re at',
    '{0}:'.format(loop_start),
    'cmp ecx, ebx  ; loop condition (check if done all array elements)',
    'je {0}'.format(loop_end),
    '; init current array elem to default value:',
    'push ebx',
    default_value_code,
    'pop ebx',
    'mov [edx + 12 + 4*ecx], eax',
    'add ecx, 1  ; increment loop counter',
    'jmp {0}'.format(loop_start),
    '{0}:'.format(loop_end),
  ]
Example #4
0
def gen_code_sit_column(sit_column, label):
  '''Generates assembly for the SIT table for this type.'''
  table_entries = []
  for ix, m in enumerate(sit_column):
    # Add an assembly comment to explain the row.
    selector = CodeGenManager.get_selector(ix)
    ret_type, (name, params) = selector
    param_strs = [str(t) for t in params]
    method_str = '{0} {1}({2})'.format(str(ret_type), name,
        ', '.join(param_strs))
    table_entries.append('; {0}'.format(method_str))

    entry = ''
    if m is None:
      entry = 'dd 0x0'
    else:
      entry = 'dd {0}'.format(m.c_defn_label)

    table_entries.append(entry)

  return [
      'global {0}'.format(label),
      '{0}:'.format(label),
      table_entries
  ]
Example #5
0
 def c_gen_code_create_array(self):
   from parser.ast.ast_type import ASTType
   type_ = ASTType.from_str(str(self.name), is_primitive=False)
   type_.definition = self
   offset = CodeGenManager.get_subtype_table_index(type_)
   return ASTClass.c_gen_code_create_array_helper(
       self.c_create_array_function_label, self.c_array_cit_label, offset)
Example #6
0
def divide_int():
  '''Divides one integer by another and returns the address of a new integer
  equal to the result.

  2 Params:
    1. The address of an integer (left operand - dividend)
    2. The address of another integer (right operand - divisor)'''
  N_PARAMS = 2

  div_not_zero = CodeGenManager.get_label('div_not_zero')

  return [
    '_divide_int:',
    common.function_prologue(),
    '; get the value for the left operand and put it in eax',
    common.get_param('eax', 0, N_PARAMS),
    common.unwrap_primitive('eax', 'eax'),
    '; get the value for the right operand and put in in ebx',
    common.get_param('ebx', 1, N_PARAMS),
    common.unwrap_primitive('ebx', 'ebx'),
    '; check for division by zero:',
    'cmp ebx, 0',
    'jne {0}'.format(div_not_zero),
    'call __exception',
    '{0}:'.format(div_not_zero),
    common.fill_high_order_bit('eax', 'edx'),
    'idiv ebx  ; sets eax to edx:eax/ebx',
    '; create an int with the result',
    'push eax  ; the result of div has to be in eax',
    'call _create_int',
    'pop ebx ; pop param',
    '; eax is an integer object with the old value of eax',
    common.function_epilogue()
  ]
Example #7
0
  def c_gen_code(self):
    before_expr_label = CodeGenManager.get_label('while_loop_expr')
    done_label = CodeGenManager.get_label('while_loop_done')

    body_code = []
    if self.statement is not None:
      body_code = self.statement.c_gen_code()

    return [
      '; while loop',
      '; expression',
      '{0}:'.format(before_expr_label),
      common.if_false(self.expression, done_label),
      body_code,
      'jmp {0}'.format(before_expr_label),
      '{0}:'.format(done_label),
    ]
Example #8
0
def check_null(src):
  '''Checks whether the value in src is null (0x0).'''
  from code_gen.manager import CodeGenManager
  check_pass = CodeGenManager.get_label('null_check_pass');
  return [
    'cmp {0}, 0'.format(src),
    'jne {0}'.format(check_pass),
    'call __exception',
    '{0}:'.format(check_pass)
  ]
Example #9
0
  def c_gen_code(self):
    if_body_code = []
    if self.if_statement is not None:
      if_body_code = self.if_statement.c_gen_code()

    else_body_code = []
    if self.else_statement is not None:
      else_body_code = self.else_statement.c_gen_code()

    false_label = CodeGenManager.get_label('if_block_false')
    if_end_label = CodeGenManager.get_label('if_block_end')
    return [
      '; if condition',
      common.if_false(self.expression, false_label),
      if_body_code,
      'jmp {0}'.format(if_end_label),
      '{0}:'.format(false_label),
      else_body_code,
      '{0}:'.format(if_end_label),
    ]
Example #10
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()
  ]
Example #11
0
def invoke_interface_method(this_reg, m, args_asm):
  '''Invokes an interface method m off this_reg using the SIT'''
  from code_gen.manager import CodeGenManager

  offset = CodeGenManager.get_sit_offset(m)
  n_params = len(m.params)
  pop_asm = ['pop ebx ; Pop param to garbage' for x in range(m.c_num_params)]

  return [
    '; Invoke interface method: {0}'.format(m.name),
    check_null('eax'),
    'push eax  ; Push "this" as the first param',
    args_asm,
    'mov dword eax, [esp + 4*{0}]  ; Get to "this"'.format(n_params),
    'mov dword eax, [eax]  ; Get to CIT for T[]',
    'mov eax, [eax]  ; Get to SIT for T[]',
    'mov eax, [eax + {0}]  ; Get the method loc in the SIT'.format(offset),
    'call eax  ; Call the method',
    pop_asm,
  ]
Example #12
0
  def c_gen_code_subtype_column_helper(label, subtype_column):
    '''Generates the subtype column given the label and the values for the type

    subtype_column is a list of boolean values corresponding to whether the
    type is a subtype of the row type.'''
    subtype_cells = []
    for ix, val in enumerate(subtype_column):
      # Add a comment for each subtype cell.
      type_ = CodeGenManager.get_subtype_table_type(ix)
      subtype_cells.append('; subtype = {0}'.format(str(type_)))

      if val:
        subtype_cells.append('dd 1')
      else:
        subtype_cells.append('dd 0')

    return [
      '; EXAMPLE',
      '; subtype = X',
      '; dd 1',
      '; X is a subtype of the contained type',
      '{0}:'.format(label),
      subtype_cells
    ]
Example #13
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),
      ]
Example #14
0
 def c_add_static_to_init(self):
   '''Add static fields to the initializtion list in CodeGenManager'''
   for f in self.fields:
     if f.is_static:
       CodeGenManager.add_static_var_to_init(self, f)
   return
Example #15
0
 def c_create_array_function_label(self):
   label = 'create_array_{0}'.format(self.canonical_name)
   return CodeGenManager.memoize_label(self, label)
Example #16
0
 def c_array_cit_label(self):
   label = 'array_cit_{0}'.format(self.canonical_name)
   return CodeGenManager.memoize_label(self, label)
Example #17
0
 def c_cit_label(self):
   label = 'class_info_{0}'.format(self.canonical_name)
   return CodeGenManager.memoize_label(self, label)
Example #18
0
 def c_array_subtype_column_label(self):
   label = 'array_subtype_column_{0}'.format(self.canonical_name)
   return CodeGenManager.memoize_label(self, label)
Example #19
0
 def c_array_sit_column_label(self):
   label = 'sit_column_{0}'.format(
       CodeGenManager.java_lang_object_defn.canonical_name)
   return CodeGenManager.memoize_label(CodeGenManager.java_lang_object_defn,
       label)
Example #20
0
 def c_sit_column_label(self):
   label = 'sit_column_{0}'.format(self.canonical_name)
   return CodeGenManager.memoize_label(self, label)
Example #21
0
 def c_defn_label(self):
   label = 'method_defn_{0}'.format(str(self.name))
   return CodeGenManager.memoize_label(self, label)
 def c_defn_label(self):
   '''The label pointing to the field definition'''
   # NOTE: This is only for static fields!  Instance fields can be obtained
   # by using the offset on the object.
   label = 'field_defn_{0}'.format(str(self.identifier))
   return CodeGenManager.memoize_label(self, label)