void n_for::code_gen(status& stat, std::ostream& out) { if (init != NULL) // initialising expression init->code_gen(stat, out); // start of loop: this is a lot like a while loop. stat.set_continue_label(); out << stat.get_continue_label() << ":\n"; stat.lock_register(out); stat.set_assign_expr(); // check expression cond->code_gen(stat, out); stat.set_break_label(); // exit loop if expression equals zero out << "\tbeqz\t$t" << stat.get_register() << "," << stat.get_break_label() << "\n"; out << "\tnop\n"; stat.unlock_register(out); stat.set_assign_expr(); // loop statement left->code_gen(stat, out); if (right != NULL) // loop expression (something like i++) right->code_gen(stat, out); out << "\tb\t" << stat.get_continue_label() << "\n"; out << "\tnop\n"; out << stat.get_break_label() << ":\n"; stat.reset_labels(true); return; }
void n_ifelse::code_gen(status& stat, std::ostream& out) { stat.lock_register(out); stat.set_assign_expr(); // check expression left->code_gen(stat, out); // branch over if statement, if the expression equals zero std::string else_label = stat.label_gen(); out << "\tbeqz\t$t" << stat.get_register() << "," << else_label << "\n"; out << "\tnop\n"; stat.unlock_register(out); stat.set_assign_expr(); // if statement right->code_gen(stat, out); if (else_node != NULL) { std::string end_label = stat.label_gen(); // branch over else statement, if if branch was executed out << "\tb\t" << end_label << "\n"; out << "\tnop\n"; out << else_label << ":\n"; // else statement else_node->code_gen(stat, out); out << end_label << ":\n"; } else { out << else_label << ":\n"; } return; }
void n_case::code_gen(status& stat, std::ostream& out) { if (left != NULL) // case: { stat.lock_register(out); stat.set_assign_expr(); int op2 = stat.get_register(); left->code_gen(stat, out); stat.unlock_register(out); stat.set_assign_expr(); std::string next_case_label = stat.label_gen(); // if the expressions are not equal, branch over statement out << "\tbne\t$t" << stat.get_register() << ",$t" << op2 << "," << next_case_label << "\n"; out << "\tnop\n"; // case body label if (stat.get_case_label() != "empty") out << stat.get_case_label() << ":\n"; stat.set_case_label(); if (right != NULL) right->code_gen(stat, out); // case body // fall through: need to jump to the next case body. out << "\tb\t" << stat.get_case_label() << "\n"; out << "\tnop\n"; out << next_case_label << ":\n"; } else // default: { if (right != NULL) right->code_gen(stat, out); } return; }
void n_init_decl::code_gen(status& stat, std::ostream& out) { if (left != NULL) { stat.set_decl(false); // let the id node know that a variable is being declared left->code_gen(stat, out); stat.set_decl(false); } if (right != NULL) // if variable is initialised to value { if (stat.global_var()) { std::stringstream amount; right->print(amount); out << "\t" << amount.str() << "\n"; } else { stat.lock_register(out); stat.set_assign_expr(); // evaluate assign expr right->code_gen(stat, out); stat.set_assign_var(); // let the id node know that a variable is being set to a value left->code_gen(stat, out); stat.set_assign_var(); stat.unlock_register(out); stat.set_assign_expr(); } } else if (stat.global_var()) out << "\n"; return; }
void n_jump_stat::code_gen(status& stat, std::ostream& out) { if (type == "continue") { out << "\tb\t" << stat.get_continue_label() << "\n"; } else if (type == "break") { out << "\tb\t" << stat.get_break_label() << "\n"; } else if (type == "return") { if (left != NULL) { stat.lock_register(out); stat.set_assign_expr(); left->code_gen(stat, out); out << "\tmove\t$v0,$t" << stat.get_register() << "\n"; stat.set_assign_expr(); stat.unlock_register(out); out << "\tb\tr" << stat.get_function_name() << "\n"; out << "\tnop\n"; } } else // goto { out << "\tj\tl_" << type << "\n"; } return; }
void n_ternary::code_gen(status& stat, std::ostream& out) { bool unlock = false; if (!stat.get_assign_expr()) { stat.lock_register(out); stat.set_assign_expr(); unlock = true; } cond->code_gen(stat, out); // the condition std::string zero_label = stat.label_gen(); out << "\tbeqz\t$t" << stat.get_register() << "," << zero_label << "\n"; out << "\tnop\n"; left->code_gen(stat, out); // the first expression std::string end_label = stat.label_gen(); out << "\tb\t" << end_label << "\n"; out << zero_label << ":\n"; right->code_gen(stat, out); // the second expression out << end_label << ":\n"; if (unlock) { stat.unlock_register(out); stat.set_assign_expr(); } return; }
void n_arg_list::code_gen(status& stat, std::ostream& out) { if (left != NULL) left->code_gen(stat, out); int arg_reg = stat.lock_arg_register(out); stat.lock_register(out); right->code_gen(stat, out); if (arg_reg < 4) out << "\tmove\t$a" << arg_reg << ",$t" << stat.get_register() << "\n"; else out << "\tsw\t$t" << stat.get_register() << ",($sp)\n"; stat.unlock_register(out); return; }
void n_switch::code_gen(status& stat, std::ostream& out) { stat.lock_register(out); stat.set_assign_expr(); // check expression left->code_gen(stat, out); stat.set_assign_expr(); stat.set_break_label(); // list of cases right->code_gen(stat, out); stat.unlock_register(out); out << stat.get_break_label() << ":\n"; out << stat.get_case_label() << ":\n"; stat.reset_labels(false); return; }
void n_dowhile::code_gen(status& stat, std::ostream& out) { // label signifying the start of the loop stat.set_continue_label(); out << stat.get_continue_label() << ":\n"; // loop statement stat.set_break_label(); left->code_gen(stat, out); stat.lock_register(out); stat.set_assign_expr(); // check expression right->code_gen(stat, out); // do another loop if expression is non zero out << "\tbnez\t$t" << stat.get_register() << "," << stat.get_continue_label() << "\n"; out << "\tnop\n"; out << stat.get_break_label() << ":\n"; stat.unlock_register(out); stat.set_assign_expr(); stat.reset_labels(true); return; }
void n_while::code_gen(status& stat, std::ostream& out) { // label signifying the start of the loop stat.set_continue_label(); out << stat.get_continue_label() << ":\n"; stat.lock_register(out); stat.set_assign_expr(); // check expression left->code_gen(stat, out); stat.set_break_label(); // exit loop if expression equals zero out << "\tbeqz\t$t" << stat.get_register() << "," << stat.get_break_label() << "\n"; out << "\tnop\n"; stat.unlock_register(out); stat.set_assign_expr(); // loop statement right->code_gen(stat, out); // return to top of loop out << "\tb\t" << stat.get_continue_label() << "\n"; out << "\tnop\n"; out << stat.get_break_label() << ":\n"; stat.reset_labels(true); return; }
void n_expression::code_gen(status& stat, std::ostream& out) { // left OP right : result_reg = t0 OP t1 bool unlock = false; if (!stat.get_assign_expr()) { stat.lock_register(out); stat.set_assign_expr(); unlock = true; } if (opstr == "+") { if (left != NULL) { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tadd.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tadd\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else { right->code_gen(stat, out); } } else if (opstr == "-") { if (left != NULL) { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tsub.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tsub\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else { stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tneg\t$t" << stat.get_register() << ",$t" << op2 << "\n"; } } else if (opstr == "*") { if (left != NULL) // if operation is left MULT right { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tmul.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tmul\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else // if operation is dereferencing { if (stat.get_assign_var()) stat.lock_register(out); int op2 = stat.get_register(); stat.set_dereference(); right->code_gen(stat, out); stat.set_dereference(); if (stat.get_assign_var()) // if variable needs to be saved stat.unlock_register(out); out << "\t" << stat.pointer_opcode() << "\t$t" << stat.get_register() << ",($t" << op2 << ")\n"; } } else if (opstr == "/") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); int op2f = stat.get_f_register(); stat.unlock_register(out); if (stat.is_float()) out << "\tdiv.s\t$f" << stat.get_f_register() << ",$f" << stat.get_f_register() << ",$f" << op2f << "\n"; else out << "\tdiv\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "%") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\trem\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "&") { if (left != NULL) // if operation is left AND right { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tand\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else // if operation is referencing { stat.set_reference(); right->code_gen(stat, out); stat.set_reference(); } } else if (opstr == "|") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tor\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "^") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\txor\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "<<") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsllv\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == ">>") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsrav\t$t" << stat.get_register(); out << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "==") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tseq\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "!=") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsne\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "<") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tslt\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == ">") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tslt\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n"; } else if (opstr == "<=") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsge\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n"; } else if (opstr == ">=") { left->code_gen(stat, out); stat.lock_register(out); right->code_gen(stat, out); int op2 = stat.get_register(); stat.unlock_register(out); out << "\tsge\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",$t" << op2 << "\n"; } else if (opstr == "++") { if (left != NULL) // postfix { left->code_gen(stat, out); int op1 = stat.get_register(); stat.lock_register(out); out << "\tadd\t$t" << stat.get_register() << ",$t" << op1 << ",1\n"; stat.set_assign_var(); left->code_gen(stat, out); stat.set_assign_var(); stat.unlock_register(out); } else if (right != NULL) // prefix { right->code_gen(stat, out); out << "\tadd\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",1\n"; stat.set_assign_var(); right->code_gen(stat, out); stat.set_assign_var(); } } else if (opstr == "--") { if (left != NULL) // postfix { left->code_gen(stat, out); int op1 = stat.get_register(); stat.lock_register(out); out << "\tsub\t$t" << stat.get_register() << ",$t" << op1 << ",1\n"; stat.set_assign_var(); left->code_gen(stat, out); stat.set_assign_var(); stat.unlock_register(out); } else if (right != NULL) // prefix { right->code_gen(stat, out); out << "\tsub\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",1\n"; stat.set_assign_var(); right->code_gen(stat, out); stat.set_assign_var(); } } else if (opstr == "[]") { if (stat.get_assign_var()) stat.lock_register(out); // get offset of first element stat.lock_register(out); int op2 = stat.get_register(); stat.set_reference(); left->code_gen(stat, out); stat.set_reference(); stat.unlock_register(out); // evaluate operation right->code_gen(stat, out); // shift the operation to get number of bytes for array offset out << "\tsll\t$t" << stat.get_register() << ",$t" << stat.get_register() << ",2\n"; // subtract array offset from first element offset out << "\tsubu\t$t" << stat.get_register() << ",$t" << op2 << ",$t" << stat.get_register() << "\n"; // store or load the variable op2 = stat.get_register(); if (stat.get_assign_var()) stat.unlock_register(out); out << "\t" << stat.pointer_opcode() << "\t$t" << stat.get_register() << ",($t" << op2 << ")\n"; } else if (opstr == "!") { left->code_gen(stat, out); out << "\tseq\t$" << stat.get_register() << ",$zero,$t" << stat.get_register(); } else if (opstr == "~") { left->code_gen(stat, out); out << "\tnot\t$" << stat.get_register() << ",$t" << stat.get_register() << "\n"; } else if (opstr == "=") { right->code_gen(stat, out); stat.set_assign_var(); left->code_gen(stat, out); stat.set_assign_var(); } if (unlock) { stat.unlock_register(out); stat.set_assign_expr(); } return; }