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
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
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
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
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
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
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)
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
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")
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
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
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
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
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)
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
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
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
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
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
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
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
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
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
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()
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
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)
def cgen_expr_bitand(node): emit_comment('cgen_expr_bitand') return expr_or_and(node, 'and')
def cgen_expr_sub(node): emit_comment('cgen_expr_sub') return expr_add_sub(node, 'sub')
def cgen_expr_mul(node): emit_comment('cgen_expr_mul') return expr_mul_mod_div(node, 'mul')
def cgen_expr_bitor(node): emit_comment('cgen_expr_bitor') return expr_or_and(node, 'or')