예제 #1
0
def gen_creation_expr(info, node, method_obj):
    canon = node.find_child("Type").canon
    if canon.endswith('[]'):
        return gen_creation_expr_array(info, node, method_obj)
    
    output = ["; START gen_creation_expr"]

    # Number of bytes we will malloc (including metadata).
    num_bytes = info.get_size(canon)

    output.append("mov eax, %i" % num_bytes)
    output.append("push ebx") # Safety
    output.append("call __malloc")
    output.append("pop ebx") # Safety

    # Zero out fields.
    output.append('mov ebx, %d' % (num_bytes / 4))
    output.extend(util.gen_zero_out(info))

    output.append("mov dword [eax], SIT~%s" % canon)
    output.append("mov dword [eax+4], SBM~%s" % canon)
    output.append("mov dword [eax+8], 0") # Not an array, so 0.
    output.append("push eax ; this pointer")

    # calculate args, push args; left-to-right
    args = list(node.find_child("Arguments").children)
    num_args = len(args)
    arg_types = []
    for arg in args:
        output.extend(gen_expr(info, arg, method_obj))
        output.append("push eax")

        if typecheck.is_array_type(arg.typ) == True:
            # '[]'s replaced with '@', so that it can be accepted.
            arg_types.append(arg.typ[:-2] + '@')
        else:
            arg_types.append(arg.typ)

    constructor_name = canon.split(".")[-1]
    label = 'CONSTRUCTOR~%s.%s~%s' % (canon, constructor_name, '~'.join(arg_types))
    output.append("call %s" % label)

    # pop args
    output.append("add esp, %i" % (num_args*4))

    # put "this" on eax
    output.append("pop eax")

    output.append("; END gen_creation_expr")

    return output
예제 #2
0
def gen_field_access_addr(info, node, method_obj):
    output = []

    # Gets the field receiver.
    obj_output = gen_expr(info, node.find_child("FieldReceiver")[0], method_obj)
    output.extend(obj_output)
    
    output.extend(util.gen_null_check())

    if typecheck.is_array_type(node[1][0].typ) == True: # Array
        output.append('add eax, %d' % 12)

    else: # Object.
        offset = info.get_field_offset(node)
        output.append("add eax, %i" % (12 + offset))

    return output
예제 #3
0
파일: codegen.py 프로젝트: holdenli/CS-444
def get_method_label(node):
    assert node.name in ['MethodDeclaration', 'ConstructorDeclaration']

    # Special case for native methods.
    # TODO: "in Joos 1W, all native methods must be static, must take a single
    # argument of type int, and must return a value of type int" should be
    # checked.

    class_name = node.obj.declared_in.name
    method_name = node.obj.name
    parameters = node.find_child('Parameters')
    param_types = []
    for param in parameters:
        if typecheck.is_array_type(param[0].canon) == True:
            # '[]'s replaced with '@', so that it can be accepted.
            param_types.append(param[0].canon[:-2] + '@')
        else:
            param_types.append(param[0].canon)

    label = ''

    # Natives methods are of the form:
    # NATIVE<canonical_type>.<method_name>
    if 'native' in node.modifiers: 
        label = 'NATIVE%s.%s' % (class_name, method_name)

    # Static methods are of the form:
    # STATICMETHOD~<canonical_type>.<method_name>~<param1>~<param2>...
    elif 'static' in node.modifiers:
        label = 'STATICMETHOD~%s.%s~%s' % (class_name, method_name, '~'.join(param_types))

    # Constructors are of the form:
    # CONSTRUCTOR~<canonical_type>.<method_name>~<param1>~<param2>...
    elif node.name == 'ConstructorDeclaration':
        label = 'CONSTRUCTOR~%s.%s~%s' % (class_name, method_name, '~'.join(param_types))

    # Instance methods are of the form:
    # METHOD~<canonical_type>.<method_name>~<param1>~<param2>...
    else:
        label = 'METHOD~%s.%s~%s' % (class_name, method_name, '~'.join(param_types))

    return label
예제 #4
0
def gen_ambiguous_name_addr(info, node, method_obj):
    assert node.name == 'Name'

    output = ['; gen_ambiguous_name_addr']

    # Loop through each identifier node, looking for a significant node.
    significant_node = None
    significant_index = -1
    for i, id_node in enumerate(node.children):
        if hasattr(id_node, 'decl') or hasattr(id_node, 'canon'):
            significant_node = id_node
            significant_index = i
            break

    assert significant_index != -1 # Did not find anything, error.

    # We have Type.something, so there must be a next node.
    # This is a Static field access.
    id_node = significant_node
    i = significant_index
    prev_type = None
    if hasattr(id_node, 'canon') and id_node.canon != None:
        assert (i + 1) < len(node.children)

        # Return address of static field.
        next_node = node[i + 1].decl # decl should be static field ASTNode
        assert next_node.name == 'FieldDeclaration'
        assert 'static' in next_node.modifiers
        output.append('mov eax, %s' % next_node.label)

        i += 2 # Processed 2 nodes.
        prev_type = next_node[1].canon # Get type from Type node

    # We have local_var.something. Move its addr to eax.
    elif id_node.decl.name == 'LocalVariableDeclaration':
        assert i == 0 # Local variable must be first identifier.

        # Get the offset from the frame pointer.
        output.append('mov eax, ebp')
        local_var_offset = id_node.decl.frame_offset * 4
        output.append('add eax, %d' % local_var_offset)

        i += 1
        prev_type = id_node.decl[0].canon # Get type from Type node

    # We have a parameter.something. Move its addr to eax.
    elif id_node.decl.name == 'Parameter':
        assert i == 0 # Parameter must be first identifier.

        # Get the offset from the frame pointer.
        output.append('mov eax, ebp')
        param_offset = (id_node.decl.frame_offset * 4)
        output.append('add eax, %d' % param_offset)

        i += 1
        prev_type = id_node.decl[0].canon # Get type from Type node

    # We have an implicit 'this' on an instance field.
    elif id_node.decl.name == 'FieldDeclaration':
        assert i == 0 # Field declaration must be first identifier.

        # Get this into eax.
        output.extend(gen_this(info, None, method_obj))

        # If the field type is array, we must get the array field.
        offset = 0
        receiver_type = info.class_obj.name
        field_name = id_node.decl.obj.name
        offset = info.get_field_offset_from_field_name(receiver_type, field_name)
        offset += 12
        prev_type = id_node.decl[1].canon # Generic type.

        # Load the field address offset.
        output.append('add eax, %d' % offset)

        i += 1

    # All the remaining things are instance fields. We have the address in eax
    # already, so we just keep going.
    while i < len(node.children):
        assert i >= 1
        assert prev_type != None
        field_node = node[i]

        assert field_node.decl.name in ['FieldDeclaration',
            'FakeFieldDeclaration']

        # Nullcheck and dereference the previous result into eax.
        output.extend(util.gen_null_check())
        output.append('mov eax, [eax]')

        # Calculate the offset of the field.
        offset = 0

        # Array; length has type Int.
        if typecheck.is_array_type(prev_type):
            assert i == (len(node.children) - 1) # Must be last element.
            offset = 12
            prev_type = 'Int'

        # Object. Must search up the object's type (in prev_type) in the field
        # index and get the offset.
        else:
            prev_type_field_list = info.field_index[prev_type]
            field_name = field_node.decl.obj.name
            temp = class_hierarchy.Temp_Field(field_name)
            offset = (prev_type_field_list.index(temp) * 4) + 12
            # Keep the type.
            prev_type = field_node.decl[1].canon

        output.append('add eax, %d' % offset)

        i += 1   
        
    output.append('; end of gen_ambiguous_name_addr')    

    return output