[deploy]移除了Backend.h和.cpp
This commit is contained in:
295
src/Backend.cpp
295
src/Backend.cpp
@@ -1,295 +0,0 @@
|
|||||||
#include "Backend.h"
|
|
||||||
using namespace sysy;
|
|
||||||
|
|
||||||
namespace sysy {
|
|
||||||
|
|
||||||
using RegId = RegManager::RegId;
|
|
||||||
|
|
||||||
string CodeGen::code_gen() {
|
|
||||||
string code;
|
|
||||||
code += module_gen(module);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::module_gen(Module *module) {
|
|
||||||
string code;
|
|
||||||
string dataCode;
|
|
||||||
string textCode;
|
|
||||||
// clear last module's label record
|
|
||||||
clearModuleRecord(module);
|
|
||||||
// generate asmcode for all global values
|
|
||||||
dataCode += globaldata_gen();
|
|
||||||
|
|
||||||
code += space + ".arch armv7ve " + eol;
|
|
||||||
code += space + ".text " + eol;
|
|
||||||
auto functions = module->getFunctions();
|
|
||||||
|
|
||||||
for (auto iter = functions->begin(); iter != functions->end(); ++iter) {
|
|
||||||
string name = iter->first;
|
|
||||||
Function *func = iter->second;
|
|
||||||
auto bblist = func->getBasicBlocks();
|
|
||||||
if (bblist.empty())
|
|
||||||
continue;
|
|
||||||
// generate asmcode for each function
|
|
||||||
textCode += function_gen(func) + eol;
|
|
||||||
}
|
|
||||||
code += (dataCode + textCode + eol);
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::functionHead_gen(Function *func) {
|
|
||||||
string code;
|
|
||||||
code += space + ".globl " + func->getName() + eol;
|
|
||||||
code += space + ".p2align " + std::to_string(int_p2align) + eol;
|
|
||||||
code += space + ".type " + func->getName() + ", %function" + eol;
|
|
||||||
code += func->getName() + ":" + eol;
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* stack structure:
|
|
||||||
*
|
|
||||||
* last function stack
|
|
||||||
* -------------------------- <-- fp point
|
|
||||||
* callee-saved regs (include fp, sp, lr)
|
|
||||||
* --------------------------
|
|
||||||
* local variables and subfunc's return value (ir inst)
|
|
||||||
* --------------------------
|
|
||||||
* arg0,arg1,arg2,arg3 (as tempory variable)
|
|
||||||
* --------------------------
|
|
||||||
* caller-saved regs
|
|
||||||
* --------------------------
|
|
||||||
* arg_x ~ arg_4
|
|
||||||
* -------------------------- <-- sp point
|
|
||||||
* next function stack
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* prologue :
|
|
||||||
* preserve callee-saved registers (lr, fp and other callee-saved regs)
|
|
||||||
* set new fp
|
|
||||||
* alloc stack space for local var/ args / return value.
|
|
||||||
* store args to stack
|
|
||||||
* */
|
|
||||||
string CodeGen::prologueCode_gen(Function *func) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* epilogue :
|
|
||||||
* free stack space
|
|
||||||
* restore sp
|
|
||||||
* restore used callee-saved register(lr, fp and other callee-saved
|
|
||||||
* regs) bx lr
|
|
||||||
*/
|
|
||||||
string CodeGen::epilogueCode_gen(Function *func) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::function_gen(Function *func) {
|
|
||||||
curFunc = func;
|
|
||||||
clearFunctionRecord(func);
|
|
||||||
string bbCode;
|
|
||||||
auto bbs = func->getBasicBlocks();
|
|
||||||
for (auto iter = bbs.begin(); iter != bbs.end(); ++iter) {
|
|
||||||
auto bb = iter->get();
|
|
||||||
bbCode += basicBlock_gen(bb);
|
|
||||||
}
|
|
||||||
string code;
|
|
||||||
string funcHead = functionHead_gen(func);
|
|
||||||
string prologueCode = prologueCode_gen(func);
|
|
||||||
string epilogueCode = epilogueCode_gen(func);
|
|
||||||
string literalPoolsCode = literalPoolsCode_gen(func);
|
|
||||||
//
|
|
||||||
code = funcHead + prologueCode + bbCode + epilogueCode + literalPoolsCode;
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::basicBlock_gen(BasicBlock *bb) {
|
|
||||||
curBB = bb;
|
|
||||||
string bbLabel = getBBLabel(bb);
|
|
||||||
string code;
|
|
||||||
code += bbLabel + ":" + eol;
|
|
||||||
for (auto &instr : bb->getInstructions()) {
|
|
||||||
auto instrType = instr->getKind();
|
|
||||||
code += instruction_gen(instr.get());
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* RegId : binaryInst_gen returns RegId as its destination operand
|
|
||||||
* code : asmcode generated by binaryInst_gen
|
|
||||||
*/
|
|
||||||
pair<RegId, string> CodeGen::binaryInst_gen(BinaryInst *bInst, RegId dstRegId) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return {dstRegId, code};
|
|
||||||
}
|
|
||||||
|
|
||||||
pair<RegId, string> CodeGen::unaryInst_gen(UnaryInst *uInst, RegId dstRegId) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return {dstRegId, code};
|
|
||||||
}
|
|
||||||
pair<RegId, string> CodeGen::allocaInst_gen(AllocaInst *aInst,
|
|
||||||
RegManager::RegId dstRegId) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return {dstRegId, code};
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::storeInst_gen(StoreInst *stInst) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
pair<RegId, string> CodeGen::loadInst_gen(LoadInst *ldInst, RegId dstRegId) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return {dstRegId, code};
|
|
||||||
}
|
|
||||||
string CodeGen::returnInst_gen(ReturnInst *retInst) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
string CodeGen::uncondBrInst_gen(UncondBrInst *ubInst) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
string CodeGen::condBrInst_gen(CondBrInst *cbInst) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
pair<RegId, string> CodeGen::callInst_gen(CallInst *callInst, RegId dstRegId) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return {dstRegId, code};
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::instruction_gen(Instruction *instr) {
|
|
||||||
string code;
|
|
||||||
string unkName = instr->getName();
|
|
||||||
RegManager::RegId dstRegId = RegManager::RNONE;
|
|
||||||
auto instrType = instr->getKind();
|
|
||||||
pair<RegId, string> tmp;
|
|
||||||
switch (instrType) {
|
|
||||||
// binary inst
|
|
||||||
case Instruction::kAdd:
|
|
||||||
case Instruction::kMul:
|
|
||||||
case Instruction::kSub: {
|
|
||||||
BinaryInst *bInst = dynamic_cast<BinaryInst *>(instr);
|
|
||||||
// registers are used only for instruction operation, consider use which
|
|
||||||
// register (any one that is free for use)
|
|
||||||
tmp = binaryInst_gen(bInst, RegManager::RANY);
|
|
||||||
code += tmp.second;
|
|
||||||
dstRegId = tmp.first;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kLoad: {
|
|
||||||
LoadInst *ldInst = dynamic_cast<LoadInst *>(instr);
|
|
||||||
tmp = loadInst_gen(ldInst, RegManager::RANY);
|
|
||||||
code += M_emitComment("load inst");
|
|
||||||
code += tmp.second;
|
|
||||||
dstRegId = tmp.first;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kStore: {
|
|
||||||
StoreInst *stInst = dynamic_cast<StoreInst *>(instr);
|
|
||||||
code += M_emitComment("store inst");
|
|
||||||
code += storeInst_gen(stInst);
|
|
||||||
return code;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kAlloca: {
|
|
||||||
AllocaInst *aInst = dynamic_cast<AllocaInst *>(instr);
|
|
||||||
tmp = allocaInst_gen(aInst, RegManager::RANY);
|
|
||||||
code += M_emitComment("alloca inst");
|
|
||||||
code += tmp.second;
|
|
||||||
dstRegId = tmp.first;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kReturn: {
|
|
||||||
ReturnInst *retInst = dynamic_cast<ReturnInst *>(instr);
|
|
||||||
code += M_emitComment("return inst");
|
|
||||||
code += returnInst_gen(retInst);
|
|
||||||
return code;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kCall: {
|
|
||||||
CallInst *cInst = dynamic_cast<CallInst *>(instr);
|
|
||||||
auto tmp = callInst_gen(cInst, RegManager::RANY);
|
|
||||||
code += tmp.second;
|
|
||||||
dstRegId = tmp.first;
|
|
||||||
if (dstRegId == RegManager::R0)
|
|
||||||
return code;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kBr: {
|
|
||||||
UncondBrInst *ubInst = dynamic_cast<UncondBrInst *>(instr);
|
|
||||||
code += uncondBrInst_gen(ubInst);
|
|
||||||
return code;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Instruction::kCondBr: {
|
|
||||||
CondBrInst *cbInst = dynamic_cast<CondBrInst *>(instr);
|
|
||||||
code += condBrInst_gen(cbInst);
|
|
||||||
return code;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
code +=
|
|
||||||
"ERROR CODE : instruction " + unkName + " is not implementation" + eol;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!instr->getType()->isVoid()) {
|
|
||||||
code += storeRegToStack_gen(dstRegId, instr);
|
|
||||||
// regm.freeReg(dstRegId);//TODO : code in here.
|
|
||||||
}
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
//
|
|
||||||
string CodeGen::globaldata_gen() {
|
|
||||||
string asmCode;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return asmCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
string CodeGen::literalPoolsCode_gen(Function *func) {
|
|
||||||
string code;
|
|
||||||
/**
|
|
||||||
*code in here
|
|
||||||
*/
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace sysy
|
|
||||||
@@ -1,217 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
/**
|
|
||||||
* 后端设计需要注意的点
|
|
||||||
*
|
|
||||||
* label分配 :
|
|
||||||
* 全局变量的label,常量的label,basicblock的label,函数入口label,函数出口label
|
|
||||||
* 全局数据处理
|
|
||||||
* 常量处理
|
|
||||||
* 临时变量的处理(包括函数参数也是临时变量)
|
|
||||||
* 函数参数的处理
|
|
||||||
* 块参数的处理 (如果SSA问题通过块传参解决则需要处理块参数)
|
|
||||||
* 函数栈空间结构的设计
|
|
||||||
* 块的遍历问题
|
|
||||||
* arm32的过程调用约定
|
|
||||||
*
|
|
||||||
* 后端测试需要注意的点
|
|
||||||
*
|
|
||||||
* 如何汇编与链接.
|
|
||||||
* qemu以及树莓派如何运行.
|
|
||||||
*/
|
|
||||||
#include <algorithm>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#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<BasicBlock *> linear_bb;
|
|
||||||
int bb_no = 0;
|
|
||||||
// function params, return value and localVar
|
|
||||||
map<Argument *, int> paramsStOffset;
|
|
||||||
map<Instruction *, int> localVarStOffset;
|
|
||||||
int retValueStOffset = 0;
|
|
||||||
size_t stOffsetAcc = 0;
|
|
||||||
// label manager
|
|
||||||
map<BasicBlock *, string> 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
|
|
||||||
//<dstReg, code>
|
|
||||||
pair<RegId, string> loadInst_gen(LoadInst *ldInst, RegId dstRegId);
|
|
||||||
string storeInst_gen(StoreInst *stInst);
|
|
||||||
pair<RegId, string> allocaInst_gen(AllocaInst *aInst, RegId dstRegId);
|
|
||||||
string returnInst_gen(ReturnInst *retInst);
|
|
||||||
pair<RegId, string> callInst_gen(CallInst *retInst, RegId dstRegId);
|
|
||||||
pair<RegId, string> binaryInst_gen(BinaryInst *bInst, RegId dstRegId);
|
|
||||||
pair<RegId, string> 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
|
|
||||||
Reference in New Issue
Block a user