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_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_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_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
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
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_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_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_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"
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
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
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