📄 codegen.cc
字号:
}syntax_code_t * st_token_t::allocate_registers(void){ return syntax_tree_t::allocate_registers();}syntax_code_t * st_identifier_t::allocate_registers(void){ syntax_tree_t::allocate_registers(); // constants are taken care of in optimize.p, // so it must be a variable put_in_register (code_gen_info); return code_gen_info;}syntax_code_t * st_number_t::allocate_registers(void){ syntax_tree_t::allocate_registers(); code_gen_info->result_register = SCRATCH_REG; // value is not really in this register, but // free_register ignores it, and generate_code for UN_OP and // BIN_OP below allocates a real register if necessary code_gen_info->result_place = R_NUMBER; code_gen_info->result_value = value; code_gen_info->registers_used = 0; return code_gen_info;}syntax_code_t * st_operator_t::allocate_registers(void){ return syntax_tree_t::allocate_registers();}syntax_code_t * st_unary_op_t::allocate_registers(void){ syntax_code_t * p; syntax_tree_t::allocate_registers(); if (operand) { p = operand->allocate_registers(); *code_gen_info = *p; if (code_gen_info->result_register == SCRATCH_REG) { // constant; no register! put_in_register (code_gen_info); } } return code_gen_info;}syntax_code_t * st_binary_op_t::allocate_registers(void){ syntax_code_t *p; syntax_tree_t::allocate_registers(); if (left_operand) { p = left_operand->allocate_registers(); *code_gen_info = *p; if ( code_gen_info->result_register == SCRATCH_REG ) { // constant; no register! put_in_register (code_gen_info); } } if (right_operand) { p = right_operand->allocate_registers(); code_gen_info->registers_used |= p->registers_used; } free_register (p->result_register); return code_gen_info;}syntax_code_t * st_statement_t::allocate_registers(void){ syntax_code_t *p; syntax_tree_t::allocate_registers(); if (next_statement) { p = next_statement->allocate_registers(); code_gen_info->registers_used |= p->registers_used; } return code_gen_info;}syntax_code_t * st_assignment_t::allocate_registers(void){ syntax_code_t * right_regs = NULL; syntax_code_t * p; syntax_tree_t::allocate_registers(); if (right_side) { right_regs = right_side->allocate_registers(); code_gen_info->registers_used = right_regs->registers_used; } if (left_side) { p = left_side->allocate_registers(); code_gen_info->registers_used = p->registers_used; free_register (p->result_register); } if (right_regs) { free_register(right_regs->result_register); p->registers_used |= right_regs->registers_used; } if (next_statement) { p = next_statement->allocate_registers(); code_gen_info->registers_used |= p->registers_used; } return code_gen_info;}syntax_code_t * st_while_t::allocate_registers(void){ syntax_code_t *p; syntax_tree_t::allocate_registers(); p = condition->allocate_registers(); code_gen_info->registers_used = p->registers_used; free_register (p->result_register); if (body) { p = body->allocate_registers(); code_gen_info->registers_used |= p->registers_used; free_register (p->result_register); } if (next_statement) { p = next_statement->allocate_registers(); code_gen_info->registers_used |= p->registers_used; } return code_gen_info;}syntax_code_t * st_if_t::allocate_registers(void){ syntax_code_t *p; syntax_tree_t::allocate_registers(); p = condition->allocate_registers(); code_gen_info->registers_used = p->registers_used; free_register (p->result_register); if (body) { p = body->allocate_registers(); code_gen_info->registers_used |= p->registers_used; free_register (p->result_register); } if (next_statement) { p = next_statement->allocate_registers(); code_gen_info->registers_used |= p->registers_used; } return code_gen_info;}syntax_code_t * st_call_t::allocate_registers(void){ syntax_code_t *p; syntax_tree_t::allocate_registers(); procedure->allocate_registers(); code_gen_info->registers_used = 0; if (next_statement) { p = next_statement->allocate_registers(); code_gen_info->registers_used |= p->registers_used; } return code_gen_info;}syntax_code_t * st_declaration_t::allocate_registers(void){ syntax_tree_t::allocate_registers(); if (next_declaration) next_declaration->allocate_registers(); return code_gen_info;}syntax_code_t * st_block_t::allocate_registers(void){ syntax_tree_t::allocate_registers(); if (declarations) declarations->allocate_registers(); if (body) body->allocate_registers(); return code_gen_info;}////////////////////////////////////////////////////////////////////////////////// Code Generation//// Each node in the syntax tree must implement the generate_code member// function. Generate_code outputs the code for the node to the output file// by using the overloaded code generation function mips_op. The optional// member function generate_lcode outputs the code to access the lvalue of// a node. It is only used for variables and currently only when making// assignments.//syntax_code_t * syntax_tree_t::generate_code(void){ dump_syntax_tree(this); die_compiler("Unexpected call to syntax_tree_t::generate_code"); return code_gen_info; // doesn't really return; just avoid complaint from g++}syntax_code_t * syntax_tree_t::generate_lcode(mips_register_t data){ UNUSED_PARAM(data); dump_syntax_tree(this); die_compiler("Unexpected call to syntax_tree_t::generate_lcode"); return code_gen_info; // doesn't really return; just avoid complaint from g++}syntax_code_t * st_token_t::generate_code(void){ return code_gen_info;}syntax_code_t * st_identifier_t::generate_code(void){ symbol_code_t *ident_code = symbol_entry->generate_code(); if (ident_code->data_place == R_LABEL) { if (symbol_entry == input_symbol) { // Input preserves all regs and is actually a subroutine. mips_op(M_JAL, ident_code->where.label); mips_op(M_MOVE, code_gen_info->result_register, SCRATCH_REG); } else mips_op(M_LW, code_gen_info->result_register, ident_code->where.label); } else if (ident_code->data_place == R_OFFSET) { mips_op(M_LW, code_gen_info->result_register, ident_code->where.offset.pos, ident_code->where.offset.reg); } return code_gen_info;}////////// Generate code for accessing the lvalue of a varaible. If the "data"// is ZERO_REG (i.e. 0) then the callee wants the address of the variable,// if "data" is != ZERO_REG, then the callee wants generate_lcode to store// the value in "data" into the varaible.//syntax_code_t * st_identifier_t::generate_lcode(mips_register_t data){ symbol_code_t *ident_code = symbol_entry->generate_code(); if (ident_code->data_place == R_LABEL) { if (data != ZERO_REG) { // If the destination is not ZERO_REG, then the caller wants // us to store the value from the register into the symbol. if (symbol_entry == output_symbol) { // Output preserves all regs and is actually a subroutine. mips_op(M_MOVE, OUTPUT_REG, data); mips_op(M_JAL, ident_code->where.label); } else mips_op(M_SW, data, ident_code->where.label); } else { // If the destination is ZERO_REG, then the caller wants // us to load the address into a register for later use. mips_op(M_LA, code_gen_info->result_register, ident_code->where.label); } } else if (ident_code->data_place == R_OFFSET) { if (data != ZERO_REG) { mips_op(M_SW, data, ident_code->where.offset.pos, ident_code->where.offset.reg); } else { mips_op(M_LA, code_gen_info->result_register, ident_code->where.offset.pos, ident_code->where.offset.reg); } } return code_gen_info;}syntax_code_t * st_number_t::generate_code(void){ return code_gen_info; // Numbers don't use registers or OPs.}syntax_code_t * st_operator_t::generate_code(void){ dump_syntax_tree(this); die_compiler("Unexpected call to st_operator_t::generate_code"); return code_gen_info; // doesn't really return; just avoid complaint from g++}syntax_code_t * st_unary_op_t::generate_code(void){ syntax_code_t * operand_code = operand->generate_code(); switch (operand_code->result_place) { case R_REGISTER: mips_op(M_MOVE, code_gen_info->result_register, operand_code->result_register); break; case R_NUMBER: mips_op(M_LI, code_gen_info->result_register, operand_code->result_value); break; default: dump_syntax_tree(operand); die_compiler("Unknown result place."); break; } token_attrib_t t = op->get_attributes(); switch (t.get_minor()) { case MIN_MINUS: mips_op(M_SUB, code_gen_info->result_register, ZERO_REG, code_gen_info->result_register); break; case MIN_ODD: mips_op(M_ANDI, code_gen_info->result_register, code_gen_info->result_register, 1); break; default: ostrstream ost; ost << "Unknown MINOR unary operator: " << t.get_minor(); die_compiler(ost.str()); break; } return code_gen_info;}syntax_code_t * st_binary_op_t::generate_code(void){ syntax_code_t * left_code; syntax_code_t * right_code; mips_register_t reg; left_code = left_operand->generate_code(); right_code = right_operand->generate_code(); switch (left_code->result_place) { case R_REGISTER: mips_op(M_MOVE, code_gen_info->result_register, left_code->result_register); break; case R_NUMBER: mips_op(M_LI, code_gen_info->result_register, left_code->result_value); break; default: dump_syntax_tree(left_operand); die_compiler("Unknown result place."); break; } switch (right_code->result_place) { case R_REGISTER: reg = right_code->result_register; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -