Example #1
0
def cgen_for(node):
    emit_comment('cgen_for')
    expr1 = node.ref_child[0]
    expr2 = node.ref_child[1]
    expr3 = node.ref_child[2]
    stmt = node.ref_child[3]
    top = ut.disFp
    l1 = create_label()
    l2 = create_label()
    node.attribute[AttName.exit_label] = l2
    if expr1.data != "nothing":
        cgen_expr(expr1)
    align_stack(top)
    emit_label(l1)
    t = cgen_expr(expr2)
    if t.attribute[AttName.type] != Type.bool:
        raise TypeError("error in node " + str(node) +
                        "\n type of the decision statement must be bool!")
    t.attribute[AttName.address].load_address()
    emit_load("$t0", "$s0")
    align_stack(top)
    emit("beqz $t0, " + l2)
    cgen_stmt(stmt)
    align_stack(top)
    if expr3.data != "nothing":
        cgen_expr(expr3)
    align_stack(top)
    emit_jump(l1)
    emit_label(l2)

    emit_li("$t6", top)
    ut.emit_add("$t6", "$t6", "$fp")
    emit_move("$sp", "$t6")

    return
Example #2
0
def cgen_expr_le(node):
    emit_comment('cgen_expr_le')
    stack_handler.add_checkpoint()

    left_child = cgen_expr(node.ref_child[0])
    right_child = cgen_expr(node.ref_child[2])

    left_child_address = left_child.get_address()
    right_child_address = right_child.get_address()

    if left_child.get_type() != right_child.get_type():
        raise TypeError("in node: \n" + node.__repr__() +
                        "\nTwo exprs must have same type.")
    elif left_child.get_type() == Type.double:
        expr_float_cmp(left_child_address, right_child_address, 'lt')
    elif left_child.get_type() == Type.int:
        left_child_address.load()
        emit_move("$s1", "$s0")
        right_child_address.load()
        emit("slt $s0, $s1, $s0")
    else:
        raise TypeError("in node: \n" + node.__repr__() +
                        "\nExprs' type isn't comparable.")

    stack_handler.back_to_last_checkpoint()
    expr_set_node_attributes(node, Type.bool)
    node.get_address().store()
    return node
Example #3
0
def cgen_new_array(node):
    emit_comment('cgen_new_array')
    stack_handler.add_checkpoint()
    len_expr = cgen_expr(node.ref_child[1])
    (member_type, dimension) = expr_type(node.ref_child[2])

    if len_expr.get_type() != Type.int:
        raise TypeError("in node: \n" + node.__repr__() +
                        "\n length of new_array isn't int.")

    len_expr_address = len_expr.get_address()
    len_expr_address.load()

    emit_li('$t0', '4')

    emit_addi('$s0', '$s0', '1')
    emit('mult $s0, $t0')
    emit('mflo $a0')
    emit_li('$v0', 9)
    emit_syscall()

    # Set length
    emit_addi('$s0', '$s0', '-1')
    emit('sw $s0, 0($v0)')
    emit_addi('$s0', '$s0', '1')

    emit_move('$s0', '$v0')

    stack_handler.back_to_last_checkpoint()
    expr_set_node_attributes(node, Type.array)
    node.get_address().store()
    node.set_array_dim(dimension + 1)
    node.set_array_member_type(member_type)
    return node
Example #4
0
def cgen_function_decl(node, label, is_member_function=False, class_name=''):
    emit_label(label)
    ut.symbolTable = ut.SymbolTable(is_member_function)
    for i in range(len(node.ref_child[2].ref_child) - 1, -1, -1):
        name, type = cgen_variable(node.ref_child[2].ref_child[i])
        if type[0]:
            type = type[1:]
            ut.symbolTable.add_param(type, name, True)
        else:
            type = type[1]
            ut.symbolTable.add_param(type, name)

    if is_member_function:
        name = 'this'
        type = class_name
        ut.symbolTable.add_param(type, name)
        ut.this_type = class_name
    else:
        ut.this_type = None

    ut.symbolTable.finish_params()
    ut.disFp = 0
    emit_move('$fp', '$sp')
    ret = cgen_stmt_block(node.ref_child[3])
    emit_move("$sp", "$fp")
    emit("jr $ra")
    # if not ret.attribute[AttName.has_return] and (node.ref_child[0].data != "void") and (label != "_____main"):
    #     raise ReturnWarning(
    #         "Function in node " + str(node) + " return anything in a path!"
    #     )
    return
Example #5
0
def cgen_expr_new(node):
    class_name = expr_ident(node.ref_child[1])
    expr_set_node_attributes(node, class_name)
    obj_size = ut.class_handler.get_object_size(class_name)
    emit_li('$a0', obj_size)
    emit_li('$v0', 9)
    emit_syscall()
    emit_move('$s0', '$v0')
    node.get_address().store()
    emit('la $s0, ' + class_name)
    emit('sw $s0, 0($v0)')
    return node
Example #6
0
def cgen_expr_leq(node):
    emit_comment('cgen_expr_leq')
    stack_handler.add_checkpoint()
    node = cgen_expr_le(node)
    node.get_address().load()
    emit_move("$s2", "$s0")

    stack_handler.back_to_last_checkpoint()

    node = cgen_expr_equal(node)
    node.get_address().load()
    emit("or $s0, $s0, $s2")
    node.get_address().store()
    return node
Example #7
0
def cgen_expr_assign(node):
    emit_comment('cgen_expr_assign')
    stack_handler.add_checkpoint()
    lvalue = cgen_lvalue(node.ref_child[0])
    rvalue_expr = cgen_expr(node.ref_child[2])

    rvalue_expr_type = rvalue_expr.get_type()
    lvalue_type = lvalue.get_type()

    if not expr_convertable(lvalue_type, rvalue_expr_type):
        raise TypeError("in node: \n" + lvalue.__repr__() +
                        rvalue_expr.__repr__() +
                        "\nrvalue and lvalue type must be equal.")

    if rvalue_expr_type == Type.array:
        if (not expr_convertable(lvalue.get_array_member_type(),
                                 rvalue_expr.get_array_member_type())) or \
                rvalue_expr.get_array_dim() != lvalue.get_array_dim():
            raise TypeError("in node: \n" + lvalue.__repr__() +
                            rvalue_expr.__repr__() +
                            "\nrvalue and lvalue member-type and "
                            "arr-dimension must be equal.")

    lvalue_address = lvalue.get_address()
    rvalue_address = rvalue_expr.get_address()

    rvalue_address.load()
    emit_move('$t0', '$s0')

    lvalue_address.store()

    emit_move('$s0', '$t0')
    stack_handler.back_to_last_checkpoint()
    expr_set_node_attributes(node, lvalue_type)
    node.get_address().store()

    if rvalue_expr_type == Type.array:
        node.set_array_dim(lvalue.get_array_dim())
        node.set_array_member_type(lvalue.get_array_member_type())

    return node
Example #8
0
def cgen_expr_equal(node):
    emit_comment('cgen_expr_equal')
    stack_handler.add_checkpoint()

    left_child = cgen_expr(node.ref_child[0])
    right_child = cgen_expr(node.ref_child[2])

    left_child_address = left_child.get_address()
    right_child_address = right_child.get_address()

    if not expr_convertable(left_child.get_type(),
                            right_child.get_type()) and not expr_convertable(
                                right_child.get_type(), left_child.get_type()):
        emit_li("$s0", 0)
    elif left_child.get_type() == Type.double:
        expr_float_cmp(left_child_address, right_child_address, 'eq')
    elif left_child.get_type() == Type.string:
        left_child_address.load()
        emit_move('$s1', '$s0')
        right_child_address.load()
        emit_move('$s2', '$s0')
        emit_li('$s0', 1)

        first_label = create_label()
        second_label = create_label()
        out_label = create_label()

        emit_label(first_label)
        emit_load_byte('$t0', '$s1')
        emit_load_byte('$t1', '$s2')
        emit_addi('$s1', '$s1', '1')
        emit_addi('$s2', '$s2', '1')
        emit('beq $t0, $t1, ' + second_label)
        emit_li('$s0', 0)
        emit_label(second_label)
        emit('beqz $t0, ' + out_label)
        emit('beqz $t1, ' + out_label)
        emit_jump(first_label)
        emit_label(out_label)

    else:
        left_child_address.load()
        emit_move('$s1', '$s0')
        right_child_address.load()
        emit("xor $t0, $s0, $s1")

        emit("slt $t1, $t0, $zero")
        emit("slt $t0, $zero, $t0")
        emit("or $t0, $t0, $t1")

        emit("li $t1, 1")
        emit("sub $s0, $t1, $t0")
        emit("")

    stack_handler.back_to_last_checkpoint()

    expr_set_node_attributes(node, Type.bool)
    node.get_address().store()
    return node
Example #9
0
def cgen_return_stmt(node):
    # checking validity of statement
    func = node.ref_parent
    while func is not None and func.data != "functiondecl":
        func = func.ref_parent

    # return isn't in any function!
    if func is None:
        raise FunctionError("Error in return node " + str(node) +
                            ", return node must be use in a funcion!")

    # return for void functions
    if node.ref_child[0].data == "nothing":
        if func.ref_child[0].data == "void":
            emit_move("$sp", "$fp")
            emit("jr $ra")
            return
        else:
            raise TypeError("Error in return statement for function in node" +
                            str(func) + ", function type must be void")

    # return for non void functions
    type = get_type(func.ref_child[0])  # type of parent function
    expr = cgen_expr(node.ref_child[0])  # expr node of return

    # checking equality of types
    # if not type[0]:  # type isn't array
    #     if type[1] != expr.attribute[AttName.type]:
    #         raise TypeError(
    #             "Error in return statement in node" + str(node) + ", type of function and return isn't match!"
    #         )
    # else:  # type is array
    #     if type[1] != expr.attribute[AttName.array_member_type]:  # checking type of members
    #         raise TypeError(
    #             "Error in return statement in node" + str(node) + ", type of function and returned array isn't match!"
    #         )
    #     if type[2] != expr.attribute[AttName.array_dim]:  # checking dimension
    #         raise TypeError(
    #             "Error in return statement in node" + str(node) +
    #             ", dimension of returned array isn't match to function array dimension!"
    #         )

    # load return statement to $v0 and jump to callee
    expr.attribute[AttName.address].load()
    emit_move("$v0", "$s0")
    emit_move("$sp", "$fp")
    emit("jr $ra")

    return node.ref_child[0].data != "nothing"
Example #10
0
def cgen_call(node):
    emit_comment('cgen_call()')
    left_child = node.ref_child[0]

    stack_handler.add_checkpoint()

    if left_child.data == 'expr':
        expr = cgen_expr(node.ref_child[0])
        function_name = expr_ident(node.ref_child[2])
        actual_node = node.ref_child[3]

        if not is_class_type(
                expr.get_type()) and expr.get_type() != Type.array:
            raise TypeError("in node: \n" + node.__repr__() +
                            "\nexpr's type isn't class or array type.")

        if expr.get_type == Type.array and function_name != 'length':
            raise TypeError(
                "in node: \n" + node.__repr__() +
                "\nwhen expr is array function_name must be length")

        argument_list = expr_atual_get_args_list(actual_node, [expr])

        argument_type_list = get_args_type_list(argument_list)

        push_arguments_to_stack(argument_list)

        ra_address = push_ra_to_stack()

        if expr.get_type() == Type.array:
            emit_load_address('$s0', '___array_length')
            return_type = Type.int
        else:
            function, function_address = get_class_function_and_its_address(
                expr.get_address(), function_name, expr.get_type(),
                argument_type_list[1:])
            function_address.load()
            return_type = function.return_type

    else:
        function_name = expr_ident(left_child)
        actual_node = node.ref_child[1]

        argument_list = expr_atual_get_args_list(actual_node, [])

        argument_type_list = get_args_type_list(argument_list)

        if ut.this_type is None:
            function = function_handler.get_function(function_name,
                                                     argument_type_list)
            function_address = None
            push_arguments_to_stack(argument_list)
        else:
            try:
                function, function_address = get_class_function_and_its_address(
                    get_this_address(), function_name, ut.this_type,
                    argument_type_list)
                push_arguments_to_stack(argument_list)
                get_this_address().load()
                new_address_on_top_of_stack(
                    ut.this_type == Type.double).store()
            except FunctionError:
                function = function_handler.get_function(
                    function_name, argument_type_list)
                function_address = None
                push_arguments_to_stack(argument_list)

        return_type = function.return_type

        ra_address = push_ra_to_stack()
        if function_address is None:
            emit_load_address('$s0', function.label)
        else:
            function_address.load()

    stack_handler.set_fp_equal_sp()

    emit_jalr('$s0')

    stack_handler.back_to_last_fp()

    ra_address.load()
    emit_move('$ra', '$s0')
    emit_move('$s0', '$v0')
    stack_handler.back_to_last_checkpoint()

    if isinstance(return_type, str):
        expr_set_node_attributes(node, return_type)
    else:
        expr_set_node_attributes(node, Type.array)
        node.set_array_member_type(return_type[0])
        node.set_array_dim(return_type[1])

    node.get_address().store()
    return node
Example #11
0
def cgen_readint(node):
    L1 = create_label()
    L2 = create_label()
    L3 = create_label()
    L4 = create_label()
    L5 = create_label()
    L6 = create_label()
    L7 = create_label()
    L8 = create_label()
    L9 = create_label()
    L10 = create_label()
    L7_ = create_label()
    L_1 = create_label()
    L_2 = create_label()
    L_3 = create_label()
    L_4 = create_label()
    L_5 = create_label()
    L_6 = create_label()
    L_7 = create_label()
    exitt = create_label()
    exit = create_label()
    LL1 = create_label()
    LL2 = create_label()
    LL3 = create_label()
    LL4 = create_label()
    LL5 = create_label()
    LL6 = create_label()
    LL7 = create_label()
    LL8 = create_label()
    expr_set_node_attributes(node, Type.int)

    emit_li('$v0', 8)
    emit_li('$a1', 400)
    emit('la $a0, __read')
    emit_li('$t0', 0)
    emit_li('$t1', 0)
    emit_li('$t4', 10)
    emit_syscall()
    emit_load_byte('$t2', '$a0')
    emit_addi('$a0', '$a0', '1')
    emit_li('$t3', 13)
    emit('bne $t3, $t2, ' + LL1)
    emit_jump(exit)
    emit_label(LL1)
    emit_li('$t3', 0)
    emit('bne $t3, $t2, ' + LL2)
    emit_jump(exit)
    emit_label(LL2)
    emit_li('$t3', 10)
    emit('bne $t3, $t2, ' + L1)
    emit_jump(exit)
    emit_label(L1)
    emit_li('$t3', 45)
    emit('bne $t3, $t2, ' + L2)
    emit_li('$t1', 1)
    emit_jump(L3)
    emit_label(L2)
    emit_li('$t3', 43)
    emit('bne $t3, $t2, ' + L4)
    emit_label(L3)
    emit_load_byte('$t2', '$a0')
    emit_addi('$a0', '$a0', '1')
    emit_label(L4)
    emit_li('$t3', 13)
    emit('bne $t2, $t3, ' + LL3)
    emit_jump(exit)
    emit_label(LL3)
    emit_li('$t3', 0)
    emit('bne $t2, $t3, ' + LL4)
    emit_jump(exit)
    emit_label(LL4)
    emit_li('$t3', 10)
    emit('bne $t2, $t3, ' + L_7)
    emit_jump(exit)
    emit_label(L_7)
    emit_addi('$t2', '$t2', '-48')
    emit_li('$t3', 0)
    emit('bge $t2, $t3, ' + L5)
    emit_li('$t1', -1)
    emit_jump(L_1)
    emit_label(L5)
    emit_li('$t3', 10)
    emit('bgt $t3, $t2, ' + L6)
    emit_li('$t1', -1)
    emit_jump(L_1)
    emit_label(L6)
    emit_li('$t3', 0)
    emit_move('$t0', '$t2')
    emit('bne $t2, $t3, ' + L_1)
    emit_load_byte('$t2', '$a0')
    emit_addi('$a0', '$a0', '1')
    emit_li('$t3', 13)
    emit('bne $t2, $t3, ' + LL5)
    emit_jump(exit)
    emit_label(LL5)
    emit_li('$t3', 0)
    emit('bne $t2, $t3, ' + LL6)
    emit_jump(exit)
    emit_label(LL6)
    emit_li('$t3', 10)
    emit('bne $t2, $t3, ' + L7)
    emit_jump(exit)
    emit_label(L7)
    emit_li('$t3', 88)
    emit('beq $t2, $t3, ' + L7_)
    emit_li('$t3', 120)
    emit('beq $t2, $t3, ' + L7_)
    emit_jump(L8)
    emit_label(L7_)
    emit_li('$t4', 16)
    emit_jump(L_1)
    emit_label(L8)
    emit_li('$t3', 48)
    emit('bge $t2, $t3, ' + L9)
    emit_li('$t1', -1)
    emit_jump(L_1)
    emit_label(L9)
    emit_li('$t3', 57)
    emit('ble $t2, $t3, ' + L10)
    emit_li('$t1', -1)
    emit_jump(L_1)
    emit_label(L10)
    emit_addi('$t2', '$t2', '-48')
    emit_move('$t0', '$t2')
    emit_label(L_1)
    emit_load_byte('$t2', '$a0')
    emit_addi('$a0', '$a0', '1')
    emit_li('$t3', 13)
    emit('bne $t2, $t3, ' + LL7)
    emit_jump(exitt)
    emit_label(LL7)
    emit_li('$t3', 0)
    emit('bne $t2, $t3, ' + LL8)
    emit_jump(exitt)
    emit_label(LL8)
    emit_li('$t3', 10)
    emit('bne $t2, $t3, ' + L_2)
    emit_jump(exitt)
    emit_label(L_2)
    emit_li('$t3', 48)
    emit('blt $t2, $t3, ' + L_5)
    emit_li('$t3', 57)
    emit('bgt $t2, $t3, ' + L_3)
    emit_addi('$t2', '$t2', '-48')
    emit('mul $t0, $t0, $t4')
    emit('add $t0, $t0, $t2')
    emit_jump(L_1)
    emit_label(L_3)
    emit_li('$t3', 65)
    emit('blt $t2, $t3, ' + L_5)
    emit_li('$t3', 70)
    emit('bgt $t2, $t3, ' + L_4)
    emit_addi('$t2', '$t2', '-55')
    emit('bge $t2, $t4, ' + L_5)
    emit('mul $t0, $t0, $t4')
    emit('add $t0, $t0, $t2')
    emit_jump(L_1)
    emit_label(L_4)
    emit_li('$t3', 97)
    emit('blt $t2, $t3, ' + L_5)
    emit_li('$t3', 102)
    emit('bgt $t2, $t3, ' + L_5)
    emit_addi('$t2', '$t2', '-87')
    emit('bge $t2, $t4, ' + L_5)
    emit('mul $t0, $t0, $t4')
    emit('add $t0, $t0, $t2')
    emit_jump(L_1)
    emit_label(L_5)
    emit_li('$t1', -1)
    emit_jump(L_1)
    emit_label(exitt)
    emit_li('$t4', -1)
    emit('bne $t4, $t1, ' + L_6)
    emit_li('$t0', 0)
    emit_jump(exit)
    emit_label(L_6)
    emit_li('$t4', 1)
    emit('bne $t4, $t1, ' + exit)
    emit('sub $t0, $zero, $t0')
    emit_label(exit)
    emit_move('$s0', '$t0')
    node.get_address().store()
    return node
Example #12
0
def push_ra_to_stack():
    emit_move('$s0', '$ra')
    ra_address = new_address_on_top_of_stack(Type.int == Type.double)
    ra_address.store()
    return ra_address