生成汇编代码,初始版本

main
wqz 3 years ago
parent 22fd5c5bb8
commit faf16ff4bd

@ -11,13 +11,18 @@ add_library(SysYParser SHARED ${ANTLR_SysYGen_CXX_OUTPUTS})
target_include_directories(SysYParser PUBLIC ${ANTLR_RUNTIME}/runtime/src)
target_link_libraries(SysYParser PUBLIC antlr4_shared)
#backend/aarch32_target.hpp backend/codegen.hpp backend/target_info.hpp
add_executable(sysyc
sysyc.cpp
IR.cpp
SysYIRGenerator.cpp
Diagnostic.cpp
backend/codegen.cpp
)
target_include_directories(sysyc PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(sysyc PRIVATE "backend")
target_include_directories(sysyc PRIVATE ".")
target_compile_options(sysyc PRIVATE -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable)
target_link_libraries(sysyc PRIVATE SysYParser)
set(THREADS_PREFER_PTHREAD_FLAG ON)

@ -1053,6 +1053,16 @@ namespace sysy
public:
void print(std::ostream &os) const;
public:
std::map<std::string, Function *> *getFunctions()
{
return &functions;
}
std::map<std::string, GlobalValue *> *getGlobalValues()
{
return &globals;
}
}; // class Module
/*!

@ -0,0 +1,331 @@
#include "codegen.hpp"
namespace backend
{
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 " + endl;
code += space + ".text " + endl;
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) + endl;
}
code += (dataCode + textCode + endl);
return code;
}
string CodeGen::functionHead_gen(Function *func)
{
string code;
code += space + ".globl " + func->getName() + endl;
code += space + ".p2align " + std::to_string(int_p2align) + endl;
code += space + ".type " + func->getName() + ", %function" + endl;
code += func->getName() + ":" + endl;
return code;
}
/**
* stack structure:
*
* last function stack
* -------------------------- <-- fp point
* callee preserved regs (include fp, sp, lr)
* --------------------------
* tempory variable(ir inst)
* --------------------------
* arg0,arg1,arg2,arg3(as tempory variable)
* --------------------------
* dynamic stack(by AllocaInst) ********
* --------------------------
* caller preserved regs
* --------------------------
* arg4 ~ argX
* -------------------------- <-- sp point
* next function stack
*
*/
/**
* prologue :
* preserve callee-saved register (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 + ":" + endl;
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" + endl;
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 backend

@ -0,0 +1,252 @@
/**
* TODO : .
*
*
*
* label : label,label,basicblocklabel,label,label
*
*
* ()
*
*
*
*
* arm32
*
*
*
* .
* qemu.
*/
#ifndef __CODEGEN_HPP_
#define __CODEGEN_HPP_
#include <string>
#include <set>
#include <iostream>
#include <algorithm>
#include <IR.h>
#include <vector>
using namespace sysy;
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 + endl)
#define M_emitComment(STR) (space + "//" + STR + endl)
#define M_emitLabel(STR) (STR + ":" + endl)
// #define REG_EXP
namespace backend
{
static const string space = string(4, ' ');
static const string endl = "\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 + endl;
}
static string
emitInst_2srcR_1dstR(string name, string srcReg0, string srcReg1, string dstReg)
{
return space + name + " " + dstReg + ", " +
srcReg0 + ", " + srcReg1 + endl;
}
//
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:
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;
}
};
}
#endif //__CODEGEN_HPP_

@ -8,15 +8,25 @@ using namespace std;
using namespace antlr4;
// #include "SysYFormatter.h"
#include "SysYIRGenerator.h"
#include "backend/codegen.hpp"
using namespace sysy;
using backend::CodeGen;
int main(int argc, char **argv) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << "inputfile\n";
int main(int argc, char **argv)
{
if (argc > 3)
{
cerr << "Usage: " << argv[0] << "inputfile [ir]\n";
return EXIT_FAILURE;
}
bool genir = false;
if (argc > 2)
{
genir = true;
}
ifstream fin(argv[1]);
if (not fin) {
if (not fin)
{
cerr << "Failed to open file " << argv[1];
return EXIT_FAILURE;
}
@ -29,7 +39,17 @@ int main(int argc, char **argv) {
SysYIRGenerator generator;
generator.visitModule(moduleAST);
auto moduleIR = generator.get();
moduleIR->print(cout);
// only generate SysY IR code
if (genir)
{
moduleIR->print(cout);
return EXIT_SUCCESS;
}
CodeGen codegen(moduleIR);
string asmCode = codegen.code_gen();
cout << asmCode << endl;
;
return EXIT_SUCCESS;
}

@ -0,0 +1,10 @@
//test add
int main(){
int a, b;
a = 10;
b = 2;
int c = a;
return a + b + c;
}
Loading…
Cancel
Save