示例#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
示例#2
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
示例#3
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
示例#4
0
def cgen_if1(expr, stmt1, stmt2):
    emit_comment('cgen_if1')
    l1 = create_label()
    l2 = create_label()
    top = ut.disFp
    t1 = cgen_expr(expr)
    if t1.attribute[AttName.type] != Type.bool:
        raise TypeError("error in node " + str(expr) +
                        "\n type of the decision statement must be bool!")
    t1.attribute[AttName.address].load_address()
    emit_load("$t0", "$s0")
    align_stack(top)
    emit("beqz $t0, " + l1)
    st1 = cgen_stmt(stmt1)
    ret = 0
    if st1.attribute[AttName.has_return]:
        ret += 1
    align_stack(top)
    emit_jump(l2)
    emit_label(l1)
    st2 = cgen_stmt(stmt2)
    if st2.attribute[AttName.has_return]:
        ret += 1
    align_stack(top)
    emit_label(l2)
    return ret
示例#5
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
示例#6
0
def cgen_constant_null(node):
    emit_comment('cgen_constant_null')
    expr_set_node_attributes(node, Type.null)

    emit("la $s0, __null")

    node.get_address().store()
    return node
示例#7
0
def cgen_global_variable(node):
    emit_comment('cgen_variable_decl')
    name, type = cgen_variable(node.ref_child[0])
    if type[0]:
        type = type[1:]
        ut.globalSymbolTable.add_variable(type, name, True, global_=True)
    else:
        type = type[1]
        ut.globalSymbolTable.add_variable(type, name, global_=True)
示例#8
0
def cgen_expr_nequal(node):
    emit_comment('cgen_expr_nequal')
    node = cgen_expr_equal(node)
    address = node.get_address()

    address.load()
    emit("li $t0, 1")
    emit("sub $s0, $t0, $s0")
    address.store()
    return node
示例#9
0
def cgen_variable_decl(node):
    emit_comment('cgen_variable_decl')
    name, type = cgen_variable(node.ref_child[0])
    if type[0]:
        type = type[1:]
        ut.symbolTable.add_variable(type, name, True)
    else:
        type = type[1]
        ut.symbolTable.add_variable(type, name)

    ut.disFp -= 4
    emit("addi $sp, $sp, -4")
示例#10
0
def cgen_if(node):
    emit_comment('cgen_if')
    length = len(node.ref_child)
    if length == 2:
        cgen_if2(node.ref_child[0], node.ref_child[1])
        node.attribute[AttName.has_return] = False
    elif length == 3:
        ret = cgen_if1(node.ref_child[0], node.ref_child[1], node.ref_child[2])
        node.attribute[AttName.has_return] = (ret == 2)
    else:
        error("An illegal pattern used in if statement!")
    return node
示例#11
0
def cgen_constant_bool(node):
    emit_comment('cgen_constant_bool')
    expr_set_node_attributes(node, Type.bool)
    child = node.ref_child[0]

    if child.data == 'true':
        emit("li $s0, 1")
    elif child.data == 'false':
        emit("li $s0, 0")

    node.get_address().store()
    return node
示例#12
0
def cgen_constant_string(node):
    emit_comment('cgen_constant_string')
    expr_set_node_attributes(node, Type.string)
    child = node.ref_child[0]

    value = child.data
    label = create_label()
    emit_data(label, '.asciiz ' + value)
    emit_data(create_label(), '.space ' + str(4 - (len(value) - 2) % 4))

    emit('la $s0, ' + label)
    node.get_address().store()
    return node
示例#13
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
示例#14
0
def cgen_constant(node):
    emit_comment('cgen_constant')
    child = node.ref_child[0]

    if child.data == 'intconstant':
        return cgen_constant_int(child.ref_child[0])
    elif child.data == 'doubleconstant':
        return cgen_constant_double(child)
    elif child.data == 'boolconstant':
        return cgen_constant_bool(child)
    elif child.data == 'stringconstant':
        return cgen_constant_string(child)
    elif child.data == 'null':
        return cgen_constant_null(child)
示例#15
0
def cgen_break(node):
    emit_comment('cgen_break')
    parent = node.ref_parent
    while parent is not None:
        data = parent.data
        if data == "whilestmt" or data == "forstmt":
            break
        parent = parent.ref_parent

    if parent is None:
        error("Error in break statement, break isn't in a loop!")

    emit_jump(parent.attribute[AttName.exit_label])
    return
示例#16
0
def cgen_readline(
        node):  # after calling this function address of the string is in $S0
    emit_comment('cgen_readline()')
    l1 = create_label()
    l2 = create_label()
    l3 = create_label()
    l4 = create_label()
    ut.disFp -= 4
    node.set_address(Address(ut.disFp, 0, False))
    node.set_type(Type.string)
    emit_addi("$sp", "$sp", "-4")
    emit('''li $v0, 8
li $a1, 400
la $a0, __read
syscall
li $a1, 1
li $a2, 0''')
    emit_label(l1)
    emit('''lbu $a2, 0($a0)
li $a3, 10''')
    emit("beq $a2, $a3, " + l2)
    emit_li('$a3', 13)
    emit("beq $a2, $a3, " + l2)
    emit_li('$a3', 0)
    emit("beq $a2, $a3, " + l2)
    emit_addi('$a1', '$a1', '1')
    emit_addi('$a0', '$a0', '1')
    emit_jump(l1)
    emit_label(l2)
    emit('''li $v0, 9
move $a0, $a1
syscall
move $v1, $v0
la $a0, __read''')
    emit_label(l3)
    emit('''lbu $a2, 0($a0)
sb $zero, 0($a0)
li $a3, 10''')
    emit("beq $a2, $a3, " + l4)
    emit_li('$a3', 13)
    emit("beq $a2, $a3, " + l4)
    emit_li('$a3', 0)
    emit("beq $a2, $a3, " + l4)
    emit('''sb $a2, 0($v0)
addi $v0, $v0, 1
addi $a0, $a0, 1''')
    emit_jump(l3)
    emit_label(l4)
    emit("sw $v1, 0($sp)")
    return node
示例#17
0
def cgen_constant_double(node):
    emit_comment('cgen_constant_double')
    expr_set_node_attributes(node, Type.double)
    child = node.ref_child[0]

    value = str(child.data).lower()
    label = create_label()

    emit_data(label, '.float ' + value)

    emit('la $t0, ' + label)
    emit_load_double('$f0', '$t0')

    node.get_address().store()
    return node
示例#18
0
def cgen_constant_int(node):
    emit_comment('cgen_constant_int')
    expr_set_node_attributes(node, Type.int)
    child = node.ref_child[0]

    value = child.data
    if node.data == 'integer':
        value = int(value, 10)
    else:
        value = int(value, 16)

    emit_32li('$s0', value)

    node.get_address().store()
    return node
示例#19
0
def cgen_if2(expr, stmt):
    emit_comment('cgen_if2')
    l1 = create_label()
    top = ut.disFp
    t1 = cgen_expr(expr)
    if t1.attribute[AttName.type] != Type.bool:
        raise TypeError("error in node " + str(expr) +
                        "\n type of the decision statement must be bool!")
    t1.attribute[AttName.address].load_address()
    emit_load("$t0", "$s0")
    align_stack(top)
    emit("beqz $t0, " + l1)
    cgen_stmt(stmt)
    align_stack(top)
    emit_label(l1)
    return
示例#20
0
def cgen_stmt_block(node):
    emit_comment('cgen_stmt_block')
    ut.symbolTable.add_scope()
    top = ut.disFp
    node.attribute[AttName.has_return] = False

    for child_node in node.ref_child:
        if child_node.data == "variabledecl":
            cgen_variable_decl(child_node)
        else:
            ret = cgen_stmt(child_node)
            if ret.attribute[AttName.has_return]:
                node.attribute[AttName.has_return] = True

    align_stack(top)

    ut.symbolTable.remove_scope()
    return node
示例#21
0
def cgen_expr_not(node):
    emit_comment('cgen_expr_not')
    stack_handler.add_checkpoint()

    child = cgen_expr(node.ref_child[1])

    if child.get_type() != Type.bool:
        raise TypeError("in node: \n" + node.__repr__() +
                        "\n expr's type is not bool.")

    child_address = child.get_address()
    child_address.load()

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

    stack_handler.back_to_last_checkpoint()
    expr_set_node_attributes(node, Type.bool)
    node.get_address().store()
    return node
示例#22
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
示例#23
0
def cgen_expr_neg(node):
    emit_comment('cgen_expr_neg')
    stack_handler.add_checkpoint()

    child = cgen_expr(node.ref_child[1])
    child_type = child.get_type()
    child_address = child.get_address()
    child_address.load()

    if child_type == Type.int:
        emit("sub $s0, $zero, $s0")
    elif child_type == Type.double:
        emit("neg.s $f0, $f0")
    else:
        raise TypeError("in node: \n" + node.__repr__() +
                        "\n expr's type is not int or double.")

    stack_handler.back_to_last_checkpoint()
    expr_set_node_attributes(node, child_type)
    node.get_address().store()
    return node
示例#24
0
def cgen_print_stmt(node):
    emit_comment('cgen_print_stmt')
    top = ut.disFp

    for child in node.ref_child:
        expr = cgen_expr(child)
        address = expr.attribute[AttName.address]
        type = expr.attribute[AttName.type]
        address.load_address()
        if type == Type.double:
            emit_load_double("$f12", "$s0")
            emit_li("$v0", 2)
            emit_syscall()
            #print_double()
        elif type == "string":
            emit_load("$a0", "$s0")
            emit_li("$v0", 4)
            emit_syscall()
        elif type == Type.bool:
            l1 = create_label()
            l2 = create_label()
            emit_load('$s0', '$s0')
            emit('beqz $s0, ' + l1)
            emit('la $a0, __true')
            emit_jump(l2)
            emit_label(l1)
            emit('la $a0, __false')
            emit_label(l2)
            emit_li("$v0", 4)
            emit_syscall()
        else:
            emit_load("$a0", "$s0")
            emit_li("$v0", 1)
            emit_syscall()

        align_stack(top)

    emit('la $a0, __newLine')
    emit_li("$v0", 4)
    emit_syscall()
示例#25
0
def cgen_stmt(node):
    emit_comment('cgen_stmt')

    child = node.ref_child[0]
    top = ut.disFp

    if child.data == "stmt":
        ret = cgen_stmt(child)
        node.attribute[AttName.has_return] = ret.attribute[AttName.has_return]
    elif child.data == "forstmt":
        cgen_for(child)
        node.attribute[AttName.has_return] = False
    elif child.data == "whilestmt":
        cgen_while(child)
        node.attribute[AttName.has_return] = False
    elif child.data == "ifstmt":
        ret = cgen_if(child)
        node.attribute[AttName.has_return] = ret.attribute[AttName.has_return]
    elif child.data == "stmtblock":
        ret = cgen_stmt_block(child)
        node.attribute[AttName.has_return] = ret.attribute[AttName.has_return]
    elif child.data == "expr":
        cgen_expr(child)
        align_stack(top)
        node.attribute[AttName.has_return] = False
    elif child.data == "breakstmt":
        cgen_break(child)
        node.attribute[AttName.has_return] = False
    elif child.data == "printstmt":
        cgen_print_stmt(child)
        node.attribute[AttName.has_return] = False
    elif child.data == "returnstmt":
        ret = cgen_return_stmt(child)
        node.attribute[AttName.has_return] = ret

    return node
示例#26
0
def cgen_expr_gr(node):
    emit_comment('cgen_expr_gr')
    (node.ref_child[0], node.ref_child[2]) = (node.ref_child[2],
                                              node.ref_child[0])
    return cgen_expr_le(node)
示例#27
0
def cgen_expr_bitand(node):
    emit_comment('cgen_expr_bitand')
    return expr_or_and(node, 'and')
示例#28
0
def cgen_expr_sub(node):
    emit_comment('cgen_expr_sub')
    return expr_add_sub(node, 'sub')
示例#29
0
def cgen_expr_mul(node):
    emit_comment('cgen_expr_mul')
    return expr_mul_mod_div(node, 'mul')
示例#30
0
def cgen_expr_bitor(node):
    emit_comment('cgen_expr_bitor')
    return expr_or_and(node, 'or')