#pragma once /** * 后端设计需要注意的点 * * label分配 : * 全局变量的label,常量的label,basicblock的label,函数入口label,函数出口label * 全局数据处理 * 常量处理 * 临时变量的处理(包括函数参数也是临时变量) * 函数参数的处理 * 块参数的处理 (如果SSA问题通过块传参解决则需要处理块参数) * 函数栈空间结构的设计 * 块的遍历问题 * arm32的过程调用约定 * * 后端测试需要注意的点 * * 如何汇编与链接. * qemu以及树莓派如何运行. */ #include #include #include #include #include "IR.h" using std::find; using std::map; using std::pair; using std::set; using std::string; using std::to_string; using std::vector; #define Macro_ERROR_MSG(...) \ do { \ fprintf(stderr, "ERROR in line-%d of %s: ", __LINE__, __FILE__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ fflush(stderr); \ exit(1); \ } while (0); #define M_emitInst(STR) (space + STR + eol) #define M_emitComment(STR) (space + "//" + STR + eol) #define M_emitLabel(STR) (STR + ":" + eol) // #define REG_EXP static const string space = string(4, ' '); static const string eol = "\n"; // only for armv7 static const int int_align = 4; static const int int_size = 4; static const int int_p2align = 2; static const int reg_size = 4; // default arm32 max imm // static const uint32_t maxMovImm = 0xFFF; static const string stackIndexReg = "fp"; static uint16_t getWordHigh(uint32_t cval) { return (cval >> 16) & 0xFFFF; } static uint16_t getWordLow(uint32_t cval) { return cval & 0xFFFF; } // static string emitInst_1srcR_noDstR(string name, string srcReg) { return space + name + " " + srcReg + eol; } static string emitInst_2srcR_1dstR(string name, string srcReg0, string srcReg1, string dstReg) { return space + name + " " + dstReg + ", " + srcReg0 + ", " + srcReg1 + eol; } namespace sysy { // class RegManager { public: //{0,1,2,3,4,5,6,7,8,9,10}; enum RegId : unsigned { R0 = 0, R1 = 1, R2 = 2, R3 = 3, R4 = 4, R5 = 5, R6 = 6, R7 = 7, R8 = 8, R9 = 9, R10 = 10, RNONE = 1024, RANY = 2048, }; static string toString(RegId reg) { if (reg == RNONE) return "RNONE"; if (reg == RANY) return "RANY"; return "r" + to_string(reg); } }; class Operand { public: using RegId = RegManager::RegId; enum Kind { kReg, kImm, }; Kind kind; union { uint32_t imm; RegId regId; }; Operand(){}; Operand(uint32_t imm) : kind(kImm), imm(imm) {} Operand(RegId regId) : kind(kReg), regId(regId) {} bool isImm(void) { return kind == kImm; } bool isReg(void) { return kind == kReg; } uint32_t getImm(void) { assert(kind == kImm); return imm; } RegId getRegId(void) { assert(kind == kReg); return regId; } string toString(void) { if (kind == kImm) return "#" + to_string(imm); else return RegManager::toString(regId); } }; class CodeGen { public: using RegId = RegManager::RegId; private: sysy::Module *module; Function *curFunc; BasicBlock *curBB; // RegManager regm; // globalValue bool loadGlobalValByMOVWT = true; // basicBlock vector linear_bb; int bb_no = 0; // function params, return value and localVar map paramsStOffset; map localVarStOffset; int retValueStOffset = 0; size_t stOffsetAcc = 0; // label manager map bb_labels; uint64_t label_no = 0; public: CodeGen(Module *module) : module(module) {} // code_gen function list string code_gen(); string module_gen(Module *module); string function_gen(Function *func); string basicBlock_gen(BasicBlock *bb); string instruction_gen(Instruction *instr); string globaldata_gen(); string prologueCode_gen(Function *func); string epilogueCode_gen(Function *func); string literalPoolsCode_gen(Function *func); string functionHead_gen(Function *func); // Module void clearModuleRecord(Module *module) { label_no = 0; } // instruction gen function list // pair loadInst_gen(LoadInst *ldInst, RegId dstRegId); string storeInst_gen(StoreInst *stInst); pair allocaInst_gen(AllocaInst *aInst, RegId dstRegId); string returnInst_gen(ReturnInst *retInst); pair callInst_gen(CallInst *retInst, RegId dstRegId); pair binaryInst_gen(BinaryInst *bInst, RegId dstRegId); pair unaryInst_gen(UnaryInst *bInst, RegId dstRegId); string uncondBrInst_gen(UncondBrInst *ubInst); string condBrInst_gen(CondBrInst *ubInst); // string storeRegToStack_gen(RegId regId, Instruction *inst) { string code; /** *code in here */ return code; } // function void clearFunctionRecord(Function *func) { localVarStOffset.clear(); paramsStOffset.clear(); retValueStOffset = 0; bb_labels.clear(); // stOffsetAcc = 0; } string getBBLabel(BasicBlock *bb) { auto t = bb_labels.find(bb); string label; if (t == bb_labels.end()) { label = ".LBB_" + to_string(label_no++); bb_labels.emplace(bb, label); } else { label = t->second; } return label; } }; } // namespace sysy