#ifndef CODEGEN_HPP #define CODEGEN_HPP #include "Function.h" #include "Instruction.h" #include "Module.h" #include "Value.h" #include "logging.hpp" #include #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 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(Instruction &); void IR2assem(ReturnInst *); void IR2assem(LoadInst *); void IR2assem(StoreInst *); void IR2assem(BranchInst *) {} void IR2assem(BinaryInst *) {} void IR2assem(AllocaInst *) {} void IR2assem(PhiInst *) {} void IR2assem(CallInst *) {} void IR2assem(GetElementPtrInst *); void IR2assem(ZextInst *) {} 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); // load the content in ptr to specified register. // only use register a_id and t_ void ptrContent2reg(Value *, int id = 0); 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"); } 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"); } std::map off; unsigned int N; Function *cur_func; Module *m; vector output; }; #endif