#ifndef CODEGEN_HPP #define CODEGEN_HPP #include "BasicBlock.h" #include "Function.h" #include "Instruction.h" #include "Module.h" #include "Value.h" #include "logging.hpp" #include #include #define ALIGN(x, align) (((x / align) + (x % align ? 1 : 0)) * align) // #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16) #define STACK_ALIGN(x) ALIGN(x, 16) using std::map; using std::string; using std::vector; class CodeGen { public: CodeGen(Module *module) : m(module) {} string print() { string result; for (auto line : output) { if (line.find(":") == string::npos and line != "") result += "\t"; // 添加缩进 result += line + "\n"; } return result; } void run(); private: void IR2assem(LoadInst *); void IR2assem(StoreInst *); void IR2assem(ReturnInst *); void IR2assem(Instruction &); void IR2assem(GetElementPtrInst *); void IR2assem(CallInst *); void IR2assem(BranchInst *); // The Instructions below will do nothing void IR2assem(AllocaInst *) {} // integration with BranchInst void IR2assem(CmpInst *) {} void IR2assem(ZextInst *) {} void IR2assem(BinaryInst *); void IR2assem(PhiInst *) {} void IR2assem(FCmpInst *) {} void IR2assem(FpToSiInst *) {} void IR2assem(SiToFpInst *) {} void stackMemAlloc(); void stackMemDealloc(); // load value `opk` to the specified register // - for constant number, just load into reg // - for global variables and pointers from alloca and GEP, read through // address // only use register a_id and t_ void value2reg(Value *, int id = 0, bool is_float = false); // load the content in ptr to specified register. // only use register a_id and t_ void ptrContent2reg(Value *, int id = 0); void compute_arg_info(Function *); string bool2branch(Instruction *); string label_in_assem(BasicBlock *bb) { return cur_func->get_name() + bb->get_name().substr(5); } int typeLen(Type *type) { if (type->is_float_type()) return 4; else if (type->is_integer_type()) { if (static_cast(type)->get_num_bits() == 32) return 4; else return 1; } else if (type->is_pointer_type()) return 8; else if (type->is_array_type()) { auto arr_tp = static_cast(type); int n = arr_tp->get_num_of_elements(); return n * typeLen(arr_tp->get_element_type()); } else { assert(false && "unexpected case while computing type-length"); } } void back2stack(Instruction *instr, string reg = "$a0") { // std::cerr << instr->print() << std::endl; string suff = suffix(typeLen(instr->get_type())); string addr = "$fp, -" + std::to_string(off[instr]); output.push_back("st" + suff + " " + reg + " " + addr); } string suffix(int len) { switch (len) { case 1: return ".b"; case 2: return ".h"; case 4: return ".w"; case 8: return ".d"; } assert(false && "no such suffix"); } bool no_stack_alloca(Instruction *instr) { if (instr->is_void()) return true; if (instr->is_cmp() or instr->is_zext()) return true; return false; } std::map off; // to $fp std::map> func_arg_off; // to $sp std::map func_arg_N; unsigned int stackN; Function *cur_func; Module *m; vector output; }; #endif