更新目录结构,修改IR结构,部分修复IR生成
This commit is contained in:
59
src/include/ASTPrinter.h
Normal file
59
src/include/ASTPrinter.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
|
||||
class ASTPrinter : public SysYBaseVisitor {
|
||||
private:
|
||||
int indentLevel = 0;
|
||||
|
||||
std::string getIndent() {
|
||||
return std::string(indentLevel * 4, ' ');
|
||||
}
|
||||
public:
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override;
|
||||
// std::any visitBType(SysYParser::BTypeContext *ctx) override;
|
||||
// std::any visitDecl(SysYParser::DeclContext *ctx) override;
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override;
|
||||
std::any visitConstDef(SysYParser::ConstDefContext *ctx) override;
|
||||
// std::any visitConstInitVal(SysYParser::ConstInitValContext *ctx) override;
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override;
|
||||
std::any visitVarDef(SysYParser::VarDefContext *ctx) override;
|
||||
std::any visitInitVal(SysYParser::InitValContext *ctx) override;
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext *ctx) override;
|
||||
// std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override;
|
||||
std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override;
|
||||
std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override;
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override;
|
||||
|
||||
// std::any visitBlockItem(SysYParser::BlockItemContext *ctx) override;
|
||||
// std::any visitStmt(SysYParser::StmtContext *ctx) override;
|
||||
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override;
|
||||
std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override;
|
||||
|
||||
// std::any visitExp(SysYParser::ExpContext *ctx) override;
|
||||
// std::any visitCond(SysYParser::CondContext *ctx) override;
|
||||
std::any visitLValue(SysYParser::LValueContext *ctx) override;
|
||||
// std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override;
|
||||
std::any visitParenExp(SysYParser::ParenExpContext *ctx) override;
|
||||
std::any visitNumber(SysYParser::NumberContext *ctx) override;
|
||||
std::any visitString(SysYParser::StringContext *ctx) override;
|
||||
// std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override;
|
||||
std::any visitCall(SysYParser::CallContext *ctx) override;
|
||||
// std::any visitUnExpOp(SysYParser::UnExpContext *ctx) override;
|
||||
// std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override;
|
||||
std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override;
|
||||
std::any visitMulExp(SysYParser::MulExpContext *ctx) override;
|
||||
std::any visitAddExp(SysYParser::AddExpContext *ctx) override;
|
||||
std::any visitRelExp(SysYParser::RelExpContext *ctx) override;
|
||||
std::any visitEqExp(SysYParser::EqExpContext *ctx) override;
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override;
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override;
|
||||
std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
|
||||
};
|
||||
217
src/include/Backend.h
Normal file
217
src/include/Backend.h
Normal file
@@ -0,0 +1,217 @@
|
||||
#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
|
||||
1319
src/include/IR.h
Normal file
1319
src/include/IR.h
Normal file
File diff suppressed because it is too large
Load Diff
241
src/include/IRBuilder.h
Normal file
241
src/include/IRBuilder.h
Normal file
@@ -0,0 +1,241 @@
|
||||
#pragma once
|
||||
|
||||
#include "IR.h"
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class IRBuilder {
|
||||
private:
|
||||
unsigned labelIndex; ///< 基本块标签编号
|
||||
unsigned tmpIndex; ///< 临时变量编号
|
||||
|
||||
BasicBlock *block; ///< 当前基本块
|
||||
BasicBlock::iterator position; ///< 当前基本块指令列表位置的迭代器
|
||||
|
||||
std::vector<BasicBlock *> trueBlocks; ///< true分支基本块列表
|
||||
std::vector<BasicBlock *> falseBlocks; ///< false分支基本块列表
|
||||
|
||||
std::vector<BasicBlock *> breakBlocks; ///< break目标块列表
|
||||
std::vector<BasicBlock *> continueBlocks; ///< continue目标块列表
|
||||
|
||||
public:
|
||||
IRBuilder() : labelIndex(0), tmpIndex(0), block(nullptr) {}
|
||||
explicit IRBuilder(BasicBlock *block) : labelIndex(0), tmpIndex(0), block(block), position(block->end()) {}
|
||||
IRBuilder(BasicBlock *block, BasicBlock::iterator position)
|
||||
: labelIndex(0), tmpIndex(0), block(block), position(position) {}
|
||||
|
||||
public:
|
||||
BasicBlock *getBasicBlock() const { return block; }
|
||||
BasicBlock::iterator getPosition() const { return position; }
|
||||
void setPosition(BasicBlock *block, BasicBlock::iterator position) {
|
||||
this->block = block;
|
||||
this->position = position;
|
||||
}
|
||||
void setPosition(BasicBlock::iterator position) { this->position = position; }
|
||||
|
||||
public:
|
||||
CallInst *createCallInst(Function *callee,
|
||||
const std::vector<Value *> &args = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new CallInst(callee, args, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
UnaryInst *createUnaryInst(Instruction::Kind kind, Type *type, Value *operand,
|
||||
const std::string &name = "") {
|
||||
|
||||
auto inst = new UnaryInst(kind, type, operand, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
UnaryInst *createNegInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kNeg, Type::getIntType(), operand,
|
||||
name);
|
||||
}
|
||||
UnaryInst *createNotInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kNot, Type::getIntType(), operand,
|
||||
name);
|
||||
}
|
||||
UnaryInst *createFtoIInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFtoI, Type::getIntType(), operand,
|
||||
name);
|
||||
}
|
||||
UnaryInst *createFNegInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kFNeg, Type::getFloatType(), operand,
|
||||
name);
|
||||
}
|
||||
UnaryInst *createIToFInst(Value *operand, const std::string &name = "") {
|
||||
return createUnaryInst(Instruction::kItoF, Type::getFloatType(), operand,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createBinaryInst(Instruction::Kind kind, Type *type, Value *lhs,
|
||||
Value *rhs, const std::string &name = "") {
|
||||
auto inst = new BinaryInst(kind, type, lhs, rhs, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
BinaryInst *createAddInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kAdd, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createSubInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kSub, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createMulInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kMul, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createDivInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kDiv, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createRemInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kRem, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createICmpEQInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpEQ, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createICmpNEInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpNE, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createICmpLTInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpLT, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createICmpLEInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpLE, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createICmpGTInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpGT, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createICmpGEInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kICmpGE, Type::getIntType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createFAddInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFAdd, Type::getFloatType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createFSubInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFSub, Type::getFloatType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createFMulInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFMul, Type::getFloatType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createFDivInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFDiv, Type::getFloatType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createFRemInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFRem, Type::getFloatType(), lhs, rhs,
|
||||
name);
|
||||
}
|
||||
BinaryInst *createFCmpEQInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpEQ, Type::getFloatType(), lhs,
|
||||
rhs, name);
|
||||
}
|
||||
BinaryInst *createFCmpNEInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpNE, Type::getFloatType(), lhs,
|
||||
rhs, name);
|
||||
}
|
||||
BinaryInst *createFCmpLTInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpLT, Type::getFloatType(), lhs,
|
||||
rhs, name);
|
||||
}
|
||||
BinaryInst *createFCmpLEInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpLE, Type::getFloatType(), lhs,
|
||||
rhs, name);
|
||||
}
|
||||
BinaryInst *createFCmpGTInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpGT, Type::getFloatType(), lhs,
|
||||
rhs, name);
|
||||
}
|
||||
BinaryInst *createFCmpGEInst(Value *lhs, Value *rhs,
|
||||
const std::string &name = "") {
|
||||
return createBinaryInst(Instruction::kFCmpGE, Type::getFloatType(), lhs,
|
||||
rhs, name);
|
||||
}
|
||||
ReturnInst *createReturnInst(Value *value = nullptr) {
|
||||
auto inst = new ReturnInst(value);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
UncondBrInst *createUncondBrInst(BasicBlock *block,
|
||||
std::vector<Value *> args) {
|
||||
auto inst = new UncondBrInst(block, args, block);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
CondBrInst *createCondBrInst(Value *condition, BasicBlock *thenBlock,
|
||||
BasicBlock *elseBlock,
|
||||
const std::vector<Value *> &thenArgs,
|
||||
const std::vector<Value *> &elseArgs) {
|
||||
auto inst = new CondBrInst(condition, thenBlock, elseBlock, thenArgs,
|
||||
elseArgs, block);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
AllocaInst *createAllocaInst(Type *type,
|
||||
const std::vector<Value *> &dims = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new AllocaInst(type, dims, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
LoadInst *createLoadInst(Value *pointer,
|
||||
const std::vector<Value *> &indices = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new LoadInst(pointer, indices, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
StoreInst *createStoreInst(Value *value, Value *pointer,
|
||||
const std::vector<Value *> &indices = {},
|
||||
const std::string &name = "") {
|
||||
auto inst = new StoreInst(value, pointer, indices, block, name);
|
||||
assert(inst);
|
||||
block->getInstructions().emplace(position, inst);
|
||||
return inst;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
78
src/include/LLVMIRGenerator.h
Normal file
78
src/include/LLVMIRGenerator.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
|
||||
class LLVMIRGenerator : public SysYBaseVisitor {
|
||||
public:
|
||||
sysy::Module* getIRModule() const { return irModule.get(); }
|
||||
|
||||
std::string generateIR(SysYParser::CompUnitContext* unit);
|
||||
std::string getIR() const { return irStream.str(); }
|
||||
|
||||
private:
|
||||
std::unique_ptr<sysy::Module> irModule; // IR数据结构
|
||||
std::stringstream irStream; // 文本输出流
|
||||
sysy::IRBuilder irBuilder; // IR构建器
|
||||
int tempCounter = 0;
|
||||
std::string currentVarType;
|
||||
// std::map<std::string, sysy::Value*> symbolTable;
|
||||
std::map<std::string, std::pair<std::string, std::string>> symbolTable;
|
||||
std::map<std::string, std::string> tmpTable;
|
||||
std::vector<std::string> globalVars;
|
||||
std::string currentFunction;
|
||||
std::string currentReturnType;
|
||||
std::vector<std::string> breakStack;
|
||||
std::vector<std::string> continueStack;
|
||||
bool hasReturn = false;
|
||||
|
||||
struct LoopLabels {
|
||||
std::string breakLabel; // break跳转的目标标签
|
||||
std::string continueLabel; // continue跳转的目标标签
|
||||
};
|
||||
std::stack<LoopLabels> loopStack; // 用于管理循环的break和continue标签
|
||||
std::string getNextTemp();
|
||||
std::string getLLVMType(const std::string&);
|
||||
sysy::Type* getSysYType(const std::string&);
|
||||
|
||||
bool inFunction = false; // 标识当前是否处于函数内部
|
||||
|
||||
// 访问方法
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext* ctx);
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx);
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext* ctx);
|
||||
std::any visitVarDef(SysYParser::VarDefContext* ctx);
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx);
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx);
|
||||
// std::any visitStmt(SysYParser::StmtContext* ctx);
|
||||
std::any visitLValue(SysYParser::LValueContext* ctx);
|
||||
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx);
|
||||
std::any visitPrimExp(SysYParser::PrimExpContext* ctx);
|
||||
std::any visitParenExp(SysYParser::ParenExpContext* ctx);
|
||||
std::any visitNumber(SysYParser::NumberContext* ctx);
|
||||
std::any visitString(SysYParser::StringContext* ctx);
|
||||
std::any visitCall(SysYParser::CallContext *ctx);
|
||||
std::any visitUnExp(SysYParser::UnExpContext* ctx);
|
||||
std::any visitMulExp(SysYParser::MulExpContext* ctx);
|
||||
std::any visitAddExp(SysYParser::AddExpContext* ctx);
|
||||
std::any visitRelExp(SysYParser::RelExpContext* ctx);
|
||||
std::any visitEqExp(SysYParser::EqExpContext* ctx);
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext* ctx);
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext* ctx);
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override;
|
||||
|
||||
// 统一创建二元操作(同时生成数据结构和文本)
|
||||
sysy::Value* createBinaryOp(SysYParser::ExpContext* lhs,
|
||||
SysYParser::ExpContext* rhs,
|
||||
sysy::Instruction::Kind opKind);
|
||||
};
|
||||
99
src/include/LLVMIRGenerator_1.h
Normal file
99
src/include/LLVMIRGenerator_1.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#pragma once
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include "IR.h" // 引入 SysY IR 头文件
|
||||
#include "IRBuilder.h"
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
|
||||
class LLVMIRGenerator : public SysYBaseVisitor {
|
||||
public:
|
||||
// 生成 IR(文本和数据结构)
|
||||
std::string generateIR(SysYParser::CompUnitContext* unit);
|
||||
|
||||
// 获取文本格式的 LLVM IR
|
||||
std::string getIR() const { return irStream.str(); }
|
||||
|
||||
// 获取 SysY IR 数据结构
|
||||
sysy::Module* getModule() const { return module.get(); }
|
||||
|
||||
private:
|
||||
// 文本输出相关
|
||||
std::stringstream irStream;
|
||||
int tempCounter = 0; // 临时变量计数器
|
||||
std::string currentVarType; // 当前变量类型(文本 IR 用)
|
||||
|
||||
// 符号表:映射变量名到 {分配地址/寄存器, 类型}(文本 IR)
|
||||
std::map<std::string, std::pair<std::string, std::string>> symbolTable;
|
||||
// 临时变量表:映射临时变量名到类型(文本 IR)
|
||||
std::map<std::string, std::string> tmpTable;
|
||||
std::vector<std::string> globalVars; // 全局变量列表(文本 IR)
|
||||
|
||||
// SysY IR 数据结构
|
||||
std::unique_ptr<sysy::Module> module; // SysY IR 模块
|
||||
// 符号表:映射变量名到 SysY IR 的 Value 指针
|
||||
std::map<std::string, sysy::Value*> irSymbolTable;
|
||||
// 临时变量表:映射临时变量名到 SysY IR 的 Value 指针
|
||||
std::map<std::string, sysy::Value*> irTmpTable;
|
||||
|
||||
// 当前上下文
|
||||
std::string currentFunction; // 当前函数名(文本 IR)
|
||||
std::string currentReturnType; // 当前函数返回类型(文本 IR)
|
||||
sysy::Function* currentIRFunction = nullptr; // 当前 SysY IR 函数
|
||||
sysy::BasicBlock* currentIRBlock = nullptr; // 当前 SysY IR 基本块
|
||||
|
||||
// 循环控制
|
||||
std::vector<std::string> breakStack; // break 标签栈(文本 IR)
|
||||
std::vector<std::string> continueStack; // continue 标签栈(文本 IR)
|
||||
bool hasReturn = false; // 是否有返回语句(文本 IR)
|
||||
|
||||
struct LoopLabels {
|
||||
std::string breakLabel; // break 跳转目标标签(文本 IR)
|
||||
std::string continueLabel; // continue 跳转目标标签(文本 IR)
|
||||
sysy::BasicBlock* irBreakBlock = nullptr; // break 跳转目标块(SysY IR)
|
||||
sysy::BasicBlock* irContinueBlock = nullptr; // continue 跳转目标块(SysY IR)
|
||||
};
|
||||
std::stack<LoopLabels> loopStack; // 管理循环的 break 和 continue 标签
|
||||
|
||||
bool inFunction = false; // 标记是否在函数内部
|
||||
|
||||
// 辅助函数(文本 IR)
|
||||
std::string getNextTemp(); // 获取下一个临时变量名
|
||||
std::string getLLVMType(const std::string& type); // 转换 SysY 类型到 LLVM 类型
|
||||
|
||||
// 辅助函数(SysY IR)
|
||||
sysy::Type* getIRType(const std::string& type); // 转换 SysY 类型到 SysY IR 类型
|
||||
std::string getIRTempName(); // 获取 SysY IR 临时变量名
|
||||
void setIRPosition(sysy::BasicBlock* block); // 设置当前 IR 插入点
|
||||
|
||||
// 访问方法
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext* ctx) override;
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext* ctx) override;
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext* ctx) override;
|
||||
std::any visitVarDef(SysYParser::VarDefContext* ctx) override;
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
|
||||
std::any visitLValue(SysYParser::LValueContext* ctx) override;
|
||||
// std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override;
|
||||
std::any visitPrimExp(SysYParser::PrimExpContext* ctx) override;
|
||||
std::any visitParenExp(SysYParser::ParenExpContext* ctx) override;
|
||||
std::any visitNumber(SysYParser::NumberContext* ctx) override;
|
||||
std::any visitString(SysYParser::StringContext* ctx) override;
|
||||
std::any visitCall(SysYParser::CallContext* ctx) override;
|
||||
std::any visitUnExp(SysYParser::UnExpContext* ctx) override;
|
||||
std::any visitMulExp(SysYParser::MulExpContext* ctx) override;
|
||||
std::any visitAddExp(SysYParser::AddExpContext* ctx) override;
|
||||
std::any visitRelExp(SysYParser::RelExpContext* ctx) override;
|
||||
std::any visitEqExp(SysYParser::EqExpContext* ctx) override;
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override;
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override;
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext* ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext* ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext* ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext* ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext* ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext* ctx) override;
|
||||
};
|
||||
340
src/include/SysYFormatter.h
Normal file
340
src/include/SysYFormatter.h
Normal file
@@ -0,0 +1,340 @@
|
||||
#pragma once
|
||||
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include <ostream>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class SysYFormatter : public SysYBaseVisitor {
|
||||
protected:
|
||||
std::ostream &os;
|
||||
int indent = 0;
|
||||
|
||||
public:
|
||||
SysYFormatter(std::ostream &os) : os(os), indent(0) {}
|
||||
|
||||
protected:
|
||||
struct Indentor {
|
||||
static constexpr int TabSize = 2;
|
||||
int &indent;
|
||||
Indentor(int &indent) : indent(indent) { indent += TabSize; }
|
||||
~Indentor() { indent -= TabSize; }
|
||||
};
|
||||
std::ostream &space() { return os << std::string(indent, ' '); }
|
||||
template <typename T>
|
||||
std::ostream &interleave(const T &container, const std::string sep = ", ") {
|
||||
auto b = container.begin(), e = container.end();
|
||||
(*b)->accept(this);
|
||||
for (b = std::next(b); b != e; b = std::next(b)) {
|
||||
os << sep;
|
||||
(*b)->accept(this);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
public:
|
||||
// virtual std::any visitModule(SysYParser::ModuleContext *ctx) override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
virtual std::any visitBtype(SysYParser::BtypeContext *ctx) override {
|
||||
os << ctx->getText();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitDecl(SysYParser::DeclContext *ctx) override {
|
||||
space();
|
||||
if (ctx->CONST())
|
||||
os << ctx->CONST()->getText() << ' ';
|
||||
ctx->btype()->accept(this);
|
||||
os << ' ';
|
||||
interleave(ctx->varDef(), ", ") << ';' << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitVarDef(SysYParser::VarDefContext *ctx) override {
|
||||
ctx->lValue()->accept(this);
|
||||
if (ctx->initValue()) {
|
||||
os << ' ' << '=' << ' ';
|
||||
ctx->initValue()->accept(this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitInitValue(SysYParser::InitValueContext *ctx) override {
|
||||
if (not ctx->exp()) {
|
||||
os << '{';
|
||||
auto values = ctx->initValue();
|
||||
if (values.size())
|
||||
interleave(values, ", ");
|
||||
os << '}';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitFunc(SysYParser::FuncContext *ctx) override {
|
||||
ctx->funcType()->accept(this);
|
||||
os << ' ' << ctx->ID()->getText() << '(';
|
||||
if (ctx->funcFParams())
|
||||
ctx->funcFParams()->accept(this);
|
||||
os << ')' << ' ';
|
||||
ctx->blockStmt()->accept(this);
|
||||
os << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override {
|
||||
os << ctx->getText();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any
|
||||
visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override {
|
||||
interleave(ctx->funcFParam(), ", ");
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any
|
||||
visitFuncFParam(SysYParser::FuncFParamContext *ctx) override {
|
||||
ctx->btype()->accept(this);
|
||||
os << ' ' << ctx->ID()->getText();
|
||||
if (not ctx->LBRACKET().empty()) {
|
||||
os << '[';
|
||||
auto exp = ctx->exp();
|
||||
if (not exp.empty()) {
|
||||
os << '[';
|
||||
interleave(exp, "][") << ']';
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitBlockStmt(SysYParser::BlockStmtContext *ctx) override {
|
||||
os << '{' << '\n';
|
||||
{
|
||||
Indentor indentor(indent);
|
||||
auto items = ctx->blockItem();
|
||||
if (not items.empty())
|
||||
interleave(items, "");
|
||||
}
|
||||
space() << ctx->RBRACE()->getText() << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual std::any visitBlockItem(SysYParser::BlockItemContext *ctx)
|
||||
// override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
// virtual std::any visitStmt(SysYParser::StmtContext *ctx) override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
virtual std::any
|
||||
visitAssignStmt(SysYParser::AssignStmtContext *ctx) override {
|
||||
space();
|
||||
ctx->lValue()->accept(this);
|
||||
os << " = ";
|
||||
ctx->exp()->accept(this);
|
||||
os << ';' << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitExpStmt(SysYParser::ExpStmtContext *ctx) override {
|
||||
space();
|
||||
ctx->exp()->accept(this);
|
||||
os << ';' << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
void wrapBlock(SysYParser::StmtContext *stmt) {
|
||||
bool isBlock = stmt->blockStmt();
|
||||
if (isBlock) {
|
||||
stmt->accept(this);
|
||||
} else {
|
||||
os << "{\n";
|
||||
{
|
||||
Indentor indentor(indent);
|
||||
stmt->accept(this);
|
||||
}
|
||||
space() << "}\n";
|
||||
}
|
||||
};
|
||||
virtual std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override {
|
||||
space();
|
||||
os << ctx->IF()->getText() << " (";
|
||||
ctx->exp()->accept(this);
|
||||
os << ") ";
|
||||
auto stmt = ctx->stmt();
|
||||
auto ifStmt = stmt[0];
|
||||
wrapBlock(ifStmt);
|
||||
if (stmt.size() == 2) {
|
||||
auto elseStmt = stmt[1];
|
||||
wrapBlock(elseStmt);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override {
|
||||
space();
|
||||
os << ctx->WHILE()->getText() << " (";
|
||||
ctx->exp()->accept(this);
|
||||
os << ") ";
|
||||
wrapBlock(ctx->stmt());
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override {
|
||||
space() << ctx->BREAK()->getText() << ';' << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any
|
||||
visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override {
|
||||
space() << ctx->CONTINUE()->getText() << ';' << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any
|
||||
visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override {
|
||||
space() << ctx->RETURN()->getText();
|
||||
if (ctx->exp()) {
|
||||
os << ' ';
|
||||
ctx->exp()->accept(this);
|
||||
}
|
||||
os << ';' << '\n';
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual std::any visitEmptyStmt(SysYParser::EmptyStmtContext *ctx)
|
||||
// override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
virtual std::any
|
||||
visitRelationExp(SysYParser::RelationExpContext *ctx) override {
|
||||
auto lhs = ctx->exp(0);
|
||||
auto rhs = ctx->exp(1);
|
||||
std::string op =
|
||||
ctx->LT() ? "<" : (ctx->LE() ? "<=" : (ctx->GT() ? ">" : ">="));
|
||||
lhs->accept(this);
|
||||
os << ' ' << op << ' ';
|
||||
rhs->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any
|
||||
visitMultiplicativeExp(SysYParser::MultiplicativeExpContext *ctx) override {
|
||||
auto lhs = ctx->exp(0);
|
||||
auto rhs = ctx->exp(1);
|
||||
std::string op = ctx->MUL() ? "*" : (ctx->DIV() ? "/" : "%");
|
||||
lhs->accept(this);
|
||||
os << ' ' << op << ' ';
|
||||
rhs->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual std::any visitLValueExp(SysYParser::LValueExpContext *ctx)
|
||||
// override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
// virtual std::any visitNumberExp(SysYParser::NumberExpContext *ctx)
|
||||
// override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
virtual std::any visitAndExp(SysYParser::AndExpContext *ctx) override {
|
||||
ctx->exp(0)->accept(this);
|
||||
os << " && ";
|
||||
ctx->exp(1)->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override {
|
||||
std::string op = ctx->ADD() ? "+" : (ctx->SUB() ? "-" : "!");
|
||||
os << op;
|
||||
ctx->exp()->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitParenExp(SysYParser::ParenExpContext *ctx) override {
|
||||
os << '(';
|
||||
ctx->exp()->accept(this);
|
||||
os << ')';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitStringExp(SysYParser::StringExpContext *ctx) override {
|
||||
return visitChildren(ctx);
|
||||
}
|
||||
|
||||
virtual std::any visitOrExp(SysYParser::OrExpContext *ctx) override {
|
||||
ctx->exp(0)->accept(this);
|
||||
os << " || ";
|
||||
ctx->exp(1)->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// virtual std::any visitCallExp(SysYParser::CallExpContext *ctx) override {
|
||||
// return visitChildren(ctx);
|
||||
// }
|
||||
|
||||
virtual std::any
|
||||
visitAdditiveExp(SysYParser::AdditiveExpContext *ctx) override {
|
||||
auto lhs = ctx->exp(0);
|
||||
auto rhs = ctx->exp(1);
|
||||
std::string op = ctx->ADD() ? "+" : "-";
|
||||
lhs->accept(this);
|
||||
os << ' ' << op << ' ';
|
||||
rhs->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitEqualExp(SysYParser::EqualExpContext *ctx) override {
|
||||
auto lhs = ctx->exp(0);
|
||||
auto rhs = ctx->exp(1);
|
||||
std::string op = ctx->EQ() ? "==" : "!=";
|
||||
lhs->accept(this);
|
||||
os << ' ' << op << ' ';
|
||||
rhs->accept(this);
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitCall(SysYParser::CallContext *ctx) override {
|
||||
os << ctx->ID()->getText() << '(';
|
||||
if (ctx->funcRParams())
|
||||
ctx->funcRParams()->accept(this);
|
||||
os << ')';
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitLValue(SysYParser::LValueContext *ctx) override {
|
||||
os << ctx->ID()->getText();
|
||||
auto exp = ctx->exp();
|
||||
if (not exp.empty()) {
|
||||
os << '[';
|
||||
interleave(exp, "][") << ']';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitNumber(SysYParser::NumberContext *ctx) override {
|
||||
os << ctx->getText();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any visitString(SysYParser::StringContext *ctx) override {
|
||||
os << ctx->getText();
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual std::any
|
||||
visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override {
|
||||
interleave(ctx->exp(), ", ");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sysy
|
||||
0
src/include/SysYIRAnalyser.h
Normal file
0
src/include/SysYIRAnalyser.h
Normal file
140
src/include/SysYIRGenerator.h
Normal file
140
src/include/SysYIRGenerator.h
Normal file
@@ -0,0 +1,140 @@
|
||||
#pragma once
|
||||
#include "IR.h"
|
||||
#include "IRBuilder.h"
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "SysYParser.h"
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <forward_list>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
class SymbolTable{
|
||||
private:
|
||||
enum Kind
|
||||
{
|
||||
kModule,
|
||||
kFunction,
|
||||
kBlock,
|
||||
};
|
||||
|
||||
std::forward_list<std::pair<Kind, std::unordered_map<std::string, Value*>>> Scopes;
|
||||
|
||||
public:
|
||||
struct ModuleScope {
|
||||
SymbolTable& tables_ref;
|
||||
ModuleScope(SymbolTable& tables) : tables_ref(tables) {
|
||||
tables.enter(kModule);
|
||||
}
|
||||
~ModuleScope() { tables_ref.exit(); }
|
||||
};
|
||||
struct FunctionScope {
|
||||
SymbolTable& tables_ref;
|
||||
FunctionScope(SymbolTable& tables) : tables_ref(tables) {
|
||||
tables.enter(kFunction);
|
||||
}
|
||||
~FunctionScope() { tables_ref.exit(); }
|
||||
};
|
||||
struct BlockScope {
|
||||
SymbolTable& tables_ref;
|
||||
BlockScope(SymbolTable& tables) : tables_ref(tables) {
|
||||
tables.enter(kBlock);
|
||||
}
|
||||
~BlockScope() { tables_ref.exit(); }
|
||||
};
|
||||
|
||||
SymbolTable() = default;
|
||||
|
||||
bool isModuleScope() const { return Scopes.front().first == kModule; }
|
||||
bool isFunctionScope() const { return Scopes.front().first == kFunction; }
|
||||
bool isBlockScope() const { return Scopes.front().first == kBlock; }
|
||||
Value *lookup(const std::string &name) const {
|
||||
for (auto &scope : Scopes) {
|
||||
auto iter = scope.second.find(name);
|
||||
if (iter != scope.second.end())
|
||||
return iter->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
auto insert(const std::string &name, Value *value) {
|
||||
assert(not Scopes.empty());
|
||||
return Scopes.front().second.emplace(name, value);
|
||||
}
|
||||
private:
|
||||
void enter(Kind kind) {
|
||||
Scopes.emplace_front();
|
||||
Scopes.front().first = kind;
|
||||
}
|
||||
void exit() {
|
||||
Scopes.pop_front();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class SysYIRGenerator : public SysYBaseVisitor {
|
||||
private:
|
||||
std::unique_ptr<Module> module;
|
||||
IRBuilder builder;
|
||||
SymbolTable symbols_table;
|
||||
|
||||
int trueBlockNum = 0, falseBlockNum = 0;
|
||||
|
||||
int d = 0, n = 0;
|
||||
vector<int> path;
|
||||
bool isalloca;
|
||||
AllocaInst *current_alloca;
|
||||
GlobalValue *current_global;
|
||||
Type* current_type;
|
||||
int numdims = 0;
|
||||
|
||||
public:
|
||||
SysYIRGenerator() = default;
|
||||
|
||||
public:
|
||||
Module *get() const { return module.get(); }
|
||||
|
||||
public:
|
||||
std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override;
|
||||
std::any visitDecl(SysYParser::DeclContext *ctx) override;
|
||||
std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override;
|
||||
std::any visitBType(SysYParser::BTypeContext *ctx) override;
|
||||
std::any visitConstDef(SysYParser::ConstDefContext *ctx) override;
|
||||
std::any visitConstInitVal(SysYParser::ConstInitValContext *ctx) override;
|
||||
std::any visitFuncType(SysYParser::FuncTypeContext* ctx) override;
|
||||
std::any visitFuncDef(SysYParser::FuncDefContext* ctx) override;
|
||||
std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override;
|
||||
std::any visitVarDef(SysYParser::VarDefContext *ctx) override;
|
||||
std::any visitInitVal(SysYParser::InitValContext *ctx) override;
|
||||
// std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override;
|
||||
// std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override;
|
||||
std::any visitBlockStmt(SysYParser::BlockStmtContext* ctx) override;
|
||||
// std::any visitStmt(SysYParser::StmtContext *ctx) override;
|
||||
std::any visitAssignStmt(SysYParser::AssignStmtContext *ctx) override;
|
||||
std::any visitIfStmt(SysYParser::IfStmtContext *ctx) override;
|
||||
std::any visitWhileStmt(SysYParser::WhileStmtContext *ctx) override;
|
||||
std::any visitBreakStmt(SysYParser::BreakStmtContext *ctx) override;
|
||||
std::any visitContinueStmt(SysYParser::ContinueStmtContext *ctx) override;
|
||||
std::any visitReturnStmt(SysYParser::ReturnStmtContext *ctx) override;
|
||||
// std::any visitExp(SysYParser::ExpContext *ctx) override;
|
||||
std::any visitLValue(SysYParser::LValueContext *ctx) override;
|
||||
std::any visitPrimExp(SysYParser::PrimExpContext *ctx) override;
|
||||
// std::any visitParenExp(SysYParser::ParenExpContext *ctx) override;
|
||||
std::any visitNumber(SysYParser::NumberContext *ctx) override;
|
||||
// std::any visitString(SysYParser::StringContext *ctx) override;
|
||||
std::any visitCall(SysYParser::CallContext *ctx) override;
|
||||
// std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override;
|
||||
// std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override;
|
||||
std::any visitUnExp(SysYParser::UnExpContext *ctx) override;
|
||||
// std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override;
|
||||
std::any visitMulExp(SysYParser::MulExpContext *ctx) override;
|
||||
std::any visitAddExp(SysYParser::AddExpContext *ctx) override;
|
||||
std::any visitRelExp(SysYParser::RelExpContext *ctx) override;
|
||||
std::any visitEqExp(SysYParser::EqExpContext *ctx) override;
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override;
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override;
|
||||
std::any visitConstExp(SysYParser::ConstExpContext *ctx) override;
|
||||
|
||||
|
||||
}; // class SysYIRGenerator
|
||||
|
||||
} // namespace sysy
|
||||
63
src/include/range.h
Normal file
63
src/include/range.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace sysy {
|
||||
|
||||
/*!
|
||||
* \defgroup utility Utilities
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \brief `range` is an simple wrapper of an iterator pair [begin, end)
|
||||
*
|
||||
* Example usage
|
||||
*
|
||||
* ```cpp
|
||||
* vector<int> v = {1,2,3};
|
||||
* auto rg = make_range(v);
|
||||
* for (auto v : rg)
|
||||
* cout << v << '\n';
|
||||
* ```
|
||||
*/
|
||||
template <typename IterT> struct range {
|
||||
using iterator = IterT;
|
||||
using value_type = typename std::iterator_traits<iterator>::value_type;
|
||||
using reference = typename std::iterator_traits<iterator>::reference;
|
||||
|
||||
private:
|
||||
iterator b;
|
||||
iterator e;
|
||||
|
||||
public:
|
||||
explicit range(iterator b, iterator e) : b(b), e(e) {}
|
||||
iterator begin() { return b; }
|
||||
iterator end() { return e; }
|
||||
iterator begin() const { return b; }
|
||||
iterator end() const { return e; }
|
||||
auto size() const { return std::distance(b, e); }
|
||||
auto empty() const { return b == e; }
|
||||
};
|
||||
|
||||
//! create `range` object from iterator pair [begin, end)
|
||||
template <typename IterT> range<IterT> make_range(IterT b, IterT e) {
|
||||
return range(b, e);
|
||||
}
|
||||
//! create `range` object from a container who has `begin()` and `end()` methods
|
||||
template <typename ContainerT>
|
||||
range<typename ContainerT::iterator> make_range(ContainerT &c) {
|
||||
return make_range(c.begin(), c.end());
|
||||
}
|
||||
//! create `range` object from a container who has `begin()` and `end()` methods
|
||||
template <typename ContainerT>
|
||||
range<typename ContainerT::const_iterator> make_range(const ContainerT &c) {
|
||||
return make_range(c.begin(), c.end());
|
||||
}
|
||||
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
} // namespace sysy
|
||||
Reference in New Issue
Block a user