📄 codegen.cc
字号:
case R_NUMBER: reg = SCRATCH_REG; mips_op(M_LI, reg, right_code->result_value); break; default: dump_syntax_tree(right_operand); die_compiler("Unknown result place."); break; } token_attrib_t t = op->get_attributes(); switch (t.get_minor()) { case MIN_PLUS: mips_op(M_ADD, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_MINUS: mips_op(M_SUB, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_TIMES: mips_op(M_MULT, code_gen_info->result_register, reg); mips_op(M_MFLO, code_gen_info->result_register); break; case MIN_SLASH: mips_op(M_DIV, code_gen_info->result_register, reg); mips_op(M_MFLO, code_gen_info->result_register); break; case MIN_EQ: mips_op(M_SEQ, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_NE: mips_op(M_SNE, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_LT: mips_op(M_SLT, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_LE: mips_op(M_SLE, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_GT: mips_op(M_SGT, code_gen_info->result_register, code_gen_info->result_register, reg); break; case MIN_GE: mips_op(M_SGE, code_gen_info->result_register, code_gen_info->result_register, reg); break; default: ostrstream ost; ost << "Unknown MINOR binary operator: " << t.get_minor(); die_compiler(ost.str()); break; } return code_gen_info;}syntax_code_t * st_statement_t::generate_code(void){ dump_syntax_tree(this); die_compiler("Unexpected call to st_statement_t::generate_code"); return code_gen_info; // doesn't really return; just avoid complaint from g++}syntax_code_t * st_assignment_t::generate_code(void){ syntax_code_t * right_code; mips_register_t reg; right_code = right_side->generate_code(); switch (right_code->result_place) { case R_REGISTER: reg = right_code->result_register; break; case R_NUMBER: reg = SCRATCH_REG; mips_op(M_LI, reg, right_code->result_value); break; default: dump_syntax_tree(right_side); die_compiler("Unknown result place."); break; } left_side->generate_lcode(reg); if (next_statement) next_statement->generate_code(); return code_gen_info;}syntax_code_t * st_while_t::generate_code(void){ mips_name_t l1; mips_name_t l2; syntax_code_t * cond_code; next_name(l1, 'l'); next_name(l2, 'l'); mips_op(l1); cond_code = condition->generate_code(); if (cond_code->result_place == R_REGISTER) mips_op(M_BEQ, cond_code->result_register, ZERO_REG, l2); else if (cond_code->result_place == R_NUMBER) { if (!cond_code->result_value) // Optimize known loop mips_op(M_B, l2); } else { dump_syntax_tree(condition); die_compiler("Unknown result place."); } if (body) body->generate_code(); mips_op(M_J, l1); mips_op(l2); if (next_statement) next_statement->generate_code(); return code_gen_info;}syntax_code_t * st_if_t::generate_code(void){ mips_name_t l1; syntax_code_t * cond_code; next_name(l1, 'l'); cond_code = condition->generate_code(); if (cond_code->result_place == R_REGISTER) mips_op(M_BEQ, cond_code->result_register, ZERO_REG, l1); else if (cond_code->result_place == R_NUMBER) { if (!cond_code->result_value) // Optimize known loop mips_op(M_B, l1); } else { dump_syntax_tree(condition); die_compiler("Unknown result place."); } if (body) body->generate_code(); mips_op(l1); if (next_statement) next_statement->generate_code(); return code_gen_info;}syntax_code_t * st_call_t::generate_code(void){ mips_src_lines (procedure->get_location()); se_procedure_t *symbol = dynamic_cast<se_procedure_t *>(procedure->get_symbol()); // should never fail if (symbol->get_scope() != predefined_scope && symbol->get_scope() != global_scope) { mips_register_t addrReg = FP_REG; scope_number_t depth = scope_depth(symbol->get_scope()); if (depth > 0) mips_cm(string("follow the static chain to ") + string(token_chars(symbol->get_name()))); for (int i = 0; i < depth; i++) { mips_op(M_LW, SCRATCH_REG2, STATIC_LINK_OFFSET, addrReg); addrReg = SCRATCH_REG2; } mips_cm("Create static link"); mips_op(M_SW, addrReg, -4, SP_REG); // WARNING: this puts data beyond the stack pointer, // which is generally an unsafe thing to do. It works // so long as nothing asynchronous (like a signal) occurs. // It really ought to be changed. } symbol_code_t * ident_code = symbol->generate_code(); if (ident_code->data_place == R_LABEL) { mips_op(M_JAL, ident_code->where.label); } else if (ident_code->data_place == R_OFFSET) { mips_op(M_LA, SCRATCH_REG2, ident_code->where.offset.pos, ident_code->where.offset.reg); mips_op(M_JAL, SCRATCH_REG2); } if (next_statement) next_statement->generate_code(); return code_gen_info;}syntax_code_t * st_declaration_t::generate_code(void){ dump_syntax_tree(this); die_compiler("Unexpected call to st_declaration_t::generate_code"); return code_gen_info; // doesn't really return; just avoid complaint from g++}syntax_code_t * st_constant_t::generate_code(void){ if (value) value->generate_code(); if (next_declaration) next_declaration->generate_code(); return code_gen_info;}syntax_code_t * st_variable_t::generate_code(void){ if (next_declaration) next_declaration->generate_code(); return code_gen_info;}syntax_code_t * st_procedure_t::generate_code(void){ se_procedure_t *proc_symbol = dynamic_cast<se_procedure_t *>(identifier->get_symbol()); // should never fail mips_src_lines(proc_symbol->declaration_location()); open_scope(proc_symbol->get_sub_scope()); if (block) { block->set_symbol(proc_symbol); block->generate_code(); } close_scope(); if (next_declaration) next_declaration->generate_code(); return code_gen_info;}syntax_code_t * st_block_t::generate_code(void){ int frameSize; int staticLinkPart; int subscope; if (declarations) declarations->generate_code(); if (symbol) subscope = symbol->get_sub_scope(); else subscope = global_scope; { ostrstream ost; ost << "Variables for scope " << subscope; mips_cm(ost.str()); } mips_op(M_DATA); for (symbol_entry_t *p = first_in_scope(subscope) ; p != NULL; p = p->next()) { p->generate_data(); } { ostrstream ost; ost << "Code for scope " << subscope; mips_cm(ost.str()); } mips_op(M_TEXT); if (symbol) { mips_op(M_ENT, symbol->get_code_gen_info()->where.label); mips_op(symbol->get_code_gen_info()->where.label); } else { mips_cm("program starts here"); mips_op(M_ENT, "start"); mips_op("start"); mips_op(M_SW, RA_REG, "startret"); } if (body) { // non-empty procedure body->allocate_registers(); } if (symbol) { int scope; // prologue: scope = symbol->get_scope(); frameSize = space_in_scope[subscope] + 8; if (scope == predefined_scope || scope == global_scope) // Don't need space for the static link if the // procedure is declared at file level. staticLinkPart = 0; else staticLinkPart = 4; mips_cm("allocate frame"); mips_op(M_ADDI, SP_REG, SP_REG, -(frameSize + staticLinkPart)); mips_op(M_SW, FP_REG, frameSize - 8, SP_REG); if (!symbol->is_leaf()) { mips_cm("non-leaf subroutine"); mips_op(M_SW, RA_REG, frameSize - 4, SP_REG); } mips_op(M_ADDI, FP_REG, SP_REG, frameSize - 8); } if (body) body->generate_code(); if (symbol) { // epilogue: if (!symbol->is_leaf()) mips_op(M_LW, RA_REG, frameSize - 4, SP_REG); mips_cm("restore fp"); mips_op(M_LW, FP_REG, frameSize - 8, SP_REG); mips_cm("discard frame"); mips_op(M_ADDI, SP_REG, SP_REG, frameSize + staticLinkPart); } mips_src_finalize(); if (symbol) { mips_op(M_JR, RA_REG); mips_op(M_END, symbol->get_code_gen_info()->where.label); } else { mips_op(M_LW, RA_REG, "startret"); mips_op(M_JR, RA_REG); mips_op(M_END, "start"); } return code_gen_info;}////////// Traverse abstract syntax tree and send output to code file//void generate_code(const char * file_name){ code.open(file_name); if (!code) { die_compiler (string("Unable to open output file: ") + string(file_name)); } switch (compiler_target) { case T_SGI: code << sgi_prologue << "\n"; break; case T_SPIM: code << spim_prologue << "\n"; break; } code << "\t.file 2,\"" << file_name << "\"\n"; if (ast_root != NULL) { // non-empty block allocate_space(); mips_cm("procedures declared here"); mips_op(M_DATA); mips_op("startret", M_WORD, 0); ast_root->generate_code(); } else { mips_cm("empty program"); mips_op(M_TEXT); mips_op(M_ENT, "start"); mips_op("start"); mips_op(M_JR, RA_REG); mips_op(M_END, "start"); }}// End of File
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -