refactor(irgen): 规范采用visitor生成
This commit is contained in:
@@ -8,8 +8,47 @@
|
||||
#include "utils/Log.h"
|
||||
|
||||
namespace ir {
|
||||
User::User(std::shared_ptr<Type> ty, std::string name)
|
||||
: Value(std::move(ty), std::move(name)) {}
|
||||
|
||||
size_t User::GetNumOperands() const { return operands_.size(); }
|
||||
|
||||
Value* User::GetOperand(size_t index) const {
|
||||
if (index >= operands_.size()) {
|
||||
throw std::out_of_range("User operand index out of range");
|
||||
}
|
||||
return operands_[index];
|
||||
}
|
||||
|
||||
void User::SetOperand(size_t index, Value* value) {
|
||||
if (index >= operands_.size()) {
|
||||
throw std::out_of_range("User operand index out of range");
|
||||
}
|
||||
if (!value) {
|
||||
throw std::runtime_error(FormatError("ir", "User operand 不能为空"));
|
||||
}
|
||||
auto* old = operands_[index];
|
||||
if (old == value) {
|
||||
return;
|
||||
}
|
||||
if (old) {
|
||||
old->RemoveUse(this, index);
|
||||
}
|
||||
operands_[index] = value;
|
||||
value->AddUse(this, index);
|
||||
}
|
||||
|
||||
void User::AddOperand(Value* value) {
|
||||
if (!value) {
|
||||
throw std::runtime_error(FormatError("ir", "User operand 不能为空"));
|
||||
}
|
||||
size_t operand_index = operands_.size();
|
||||
operands_.push_back(value);
|
||||
value->AddUse(this, operand_index);
|
||||
}
|
||||
|
||||
Instruction::Instruction(Opcode op, std::shared_ptr<Type> ty, std::string name)
|
||||
: Value(std::move(ty), std::move(name)), opcode_(op) {}
|
||||
: User(std::move(ty), std::move(name)), opcode_(op) {}
|
||||
|
||||
Opcode Instruction::GetOpcode() const { return opcode_; }
|
||||
|
||||
@@ -21,48 +60,43 @@ void Instruction::SetParent(BasicBlock* parent) { parent_ = parent; }
|
||||
|
||||
BinaryInst::BinaryInst(Opcode op, std::shared_ptr<Type> ty, Value* lhs,
|
||||
Value* rhs, std::string name)
|
||||
: Instruction(op, std::move(ty), std::move(name)), lhs_(lhs), rhs_(rhs) {
|
||||
: Instruction(op, std::move(ty), std::move(name)) {
|
||||
if (op != Opcode::Add) {
|
||||
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 Add"));
|
||||
}
|
||||
if (!lhs_ || !rhs_) {
|
||||
if (!lhs || !rhs) {
|
||||
throw std::runtime_error(FormatError("ir", "BinaryInst 缺少操作数"));
|
||||
}
|
||||
if (!type_ || !lhs_->GetType() || !rhs_->GetType()) {
|
||||
if (!type_ || !lhs->GetType() || !rhs->GetType()) {
|
||||
throw std::runtime_error(FormatError("ir", "BinaryInst 缺少类型信息"));
|
||||
}
|
||||
if (lhs_->GetType()->GetKind() != rhs_->GetType()->GetKind() ||
|
||||
type_->GetKind() != lhs_->GetType()->GetKind()) {
|
||||
if (lhs->GetType()->GetKind() != rhs->GetType()->GetKind() ||
|
||||
type_->GetKind() != lhs->GetType()->GetKind()) {
|
||||
throw std::runtime_error(FormatError("ir", "BinaryInst 类型不匹配"));
|
||||
}
|
||||
if (!type_->IsInt32()) {
|
||||
throw std::runtime_error(FormatError("ir", "BinaryInst 当前只支持 i32"));
|
||||
}
|
||||
if (lhs_) {
|
||||
lhs_->AddUser(this);
|
||||
}
|
||||
if (rhs_) {
|
||||
rhs_->AddUser(this);
|
||||
}
|
||||
AddOperand(lhs);
|
||||
AddOperand(rhs);
|
||||
}
|
||||
|
||||
Value* BinaryInst::GetLhs() const { return lhs_; }
|
||||
Value* BinaryInst::GetLhs() const { return GetOperand(0); }
|
||||
|
||||
Value* BinaryInst::GetRhs() const { return rhs_; }
|
||||
Value* BinaryInst::GetRhs() const { return GetOperand(1); }
|
||||
|
||||
ReturnInst::ReturnInst(std::shared_ptr<Type> void_ty, Value* val)
|
||||
: Instruction(Opcode::Ret, std::move(void_ty), ""),
|
||||
value_(val) {
|
||||
if (!value_) {
|
||||
: Instruction(Opcode::Ret, std::move(void_ty), "") {
|
||||
if (!val) {
|
||||
throw std::runtime_error(FormatError("ir", "ReturnInst 缺少返回值"));
|
||||
}
|
||||
if (!type_ || !type_->IsVoid()) {
|
||||
throw std::runtime_error(FormatError("ir", "ReturnInst 返回类型必须为 void"));
|
||||
}
|
||||
value_->AddUser(this);
|
||||
AddOperand(val);
|
||||
}
|
||||
|
||||
Value* ReturnInst::GetValue() const { return value_; }
|
||||
Value* ReturnInst::GetValue() const { return GetOperand(0); }
|
||||
|
||||
AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name)
|
||||
: Instruction(Opcode::Alloca, std::move(ptr_ty), std::move(name)) {
|
||||
@@ -72,49 +106,46 @@ AllocaInst::AllocaInst(std::shared_ptr<Type> ptr_ty, std::string name)
|
||||
}
|
||||
|
||||
LoadInst::LoadInst(std::shared_ptr<Type> val_ty, Value* ptr, std::string name)
|
||||
: Instruction(Opcode::Load, std::move(val_ty), std::move(name)),
|
||||
ptr_(ptr) {
|
||||
if (!ptr_) {
|
||||
: Instruction(Opcode::Load, std::move(val_ty), std::move(name)) {
|
||||
if (!ptr) {
|
||||
throw std::runtime_error(FormatError("ir", "LoadInst 缺少 ptr"));
|
||||
}
|
||||
if (!type_ || !type_->IsInt32()) {
|
||||
throw std::runtime_error(FormatError("ir", "LoadInst 当前只支持加载 i32"));
|
||||
}
|
||||
if (!ptr_->GetType() || !ptr_->GetType()->IsPtrInt32()) {
|
||||
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("ir", "LoadInst 当前只支持从 i32* 加载"));
|
||||
}
|
||||
ptr_->AddUser(this);
|
||||
AddOperand(ptr);
|
||||
}
|
||||
|
||||
Value* LoadInst::GetPtr() const { return ptr_; }
|
||||
Value* LoadInst::GetPtr() const { return GetOperand(0); }
|
||||
|
||||
StoreInst::StoreInst(std::shared_ptr<Type> void_ty, Value* val, Value* ptr)
|
||||
: Instruction(Opcode::Store, std::move(void_ty), ""),
|
||||
value_(val),
|
||||
ptr_(ptr) {
|
||||
if (!value_) {
|
||||
: Instruction(Opcode::Store, std::move(void_ty), "") {
|
||||
if (!val) {
|
||||
throw std::runtime_error(FormatError("ir", "StoreInst 缺少 value"));
|
||||
}
|
||||
if (!ptr_) {
|
||||
if (!ptr) {
|
||||
throw std::runtime_error(FormatError("ir", "StoreInst 缺少 ptr"));
|
||||
}
|
||||
if (!type_ || !type_->IsVoid()) {
|
||||
throw std::runtime_error(FormatError("ir", "StoreInst 返回类型必须为 void"));
|
||||
}
|
||||
if (!value_->GetType() || !value_->GetType()->IsInt32()) {
|
||||
if (!val->GetType() || !val->GetType()->IsInt32()) {
|
||||
throw std::runtime_error(FormatError("ir", "StoreInst 当前只支持存储 i32"));
|
||||
}
|
||||
if (!ptr_->GetType() || !ptr_->GetType()->IsPtrInt32()) {
|
||||
if (!ptr->GetType() || !ptr->GetType()->IsPtrInt32()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("ir", "StoreInst 当前只支持写入 i32*"));
|
||||
}
|
||||
value_->AddUser(this);
|
||||
ptr_->AddUser(this);
|
||||
AddOperand(val);
|
||||
AddOperand(ptr);
|
||||
}
|
||||
|
||||
Value* StoreInst::GetValue() const { return value_; }
|
||||
Value* StoreInst::GetValue() const { return GetOperand(0); }
|
||||
|
||||
Value* StoreInst::GetPtr() const { return ptr_; }
|
||||
Value* StoreInst::GetPtr() const { return GetOperand(1); }
|
||||
|
||||
} // namespace ir
|
||||
|
||||
@@ -17,58 +17,91 @@ std::string GetLValueName(SysYParser::LValueContext& lvalue) {
|
||||
|
||||
} // namespace
|
||||
|
||||
void IRGenImpl::GenBlock(SysYParser::BlockStmtContext& block) {
|
||||
for (auto* item : block.blockItem()) {
|
||||
std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
|
||||
}
|
||||
for (auto* item : ctx->blockItem()) {
|
||||
if (item) {
|
||||
if (GenBlockItem(*item)) {
|
||||
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
|
||||
// 当前语法要求 return 为块内最后一条语句;命中后可停止生成。
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
bool IRGenImpl::GenBlockItem(SysYParser::BlockItemContext& item) {
|
||||
if (item.decl()) {
|
||||
GenDecl(*item.decl());
|
||||
return false;
|
||||
IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult(
|
||||
SysYParser::BlockItemContext& item) {
|
||||
return std::any_cast<BlockFlow>(item.accept(this));
|
||||
}
|
||||
|
||||
std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少块内项"));
|
||||
}
|
||||
if (item.stmt()) {
|
||||
return GenStmt(*item.stmt());
|
||||
if (ctx->decl()) {
|
||||
ctx->decl()->accept(this);
|
||||
return BlockFlow::Continue;
|
||||
}
|
||||
if (ctx->stmt()) {
|
||||
return ctx->stmt()->accept(this);
|
||||
}
|
||||
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
|
||||
}
|
||||
|
||||
void IRGenImpl::GenDecl(SysYParser::DeclContext& decl) {
|
||||
if (!decl.btype() || !decl.btype()->INT()) {
|
||||
// 变量声明的 IR 生成目前也是最小实现:
|
||||
// - 先检查声明的基础类型,当前仅支持局部 int;
|
||||
// - 再把 Decl 中的变量定义交给 visitVarDef 继续处理。
|
||||
//
|
||||
// 和更完整的版本相比,这里还没有:
|
||||
// - 一个 Decl 中多个变量定义的顺序处理;
|
||||
// - const、数组、全局变量等不同声明形态;
|
||||
// - 更丰富的类型系统。
|
||||
std::any IRGenImpl::visitDecl(SysYParser::DeclContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少变量声明"));
|
||||
}
|
||||
if (!ctx->btype() || !ctx->btype()->INT()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持局部 int 变量声明"));
|
||||
}
|
||||
auto* var_def = decl.varDef();
|
||||
auto* var_def = ctx->varDef();
|
||||
if (!var_def) {
|
||||
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
|
||||
}
|
||||
GenVarDef(*var_def);
|
||||
var_def->accept(this);
|
||||
return {};
|
||||
}
|
||||
|
||||
void IRGenImpl::GenVarDef(SysYParser::VarDefContext& decl) {
|
||||
if (!decl.lValue()) {
|
||||
|
||||
// 当前仍是教学用的最小版本,因此这里只支持:
|
||||
// - 局部 int 变量;
|
||||
// - 标量初始化;
|
||||
// - 一个 VarDef 对应一个槽位。
|
||||
std::any IRGenImpl::visitVarDef(SysYParser::VarDefContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少变量定义"));
|
||||
}
|
||||
if (!ctx->lValue()) {
|
||||
throw std::runtime_error(FormatError("irgen", "变量声明缺少名称"));
|
||||
}
|
||||
GetLValueName(*decl.lValue());
|
||||
if (storage_map_.find(&decl) != storage_map_.end()) {
|
||||
GetLValueName(*ctx->lValue());
|
||||
if (storage_map_.find(ctx) != storage_map_.end()) {
|
||||
throw std::runtime_error(FormatError("irgen", "声明重复生成存储槽位"));
|
||||
}
|
||||
auto* slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
|
||||
storage_map_[&decl] = slot;
|
||||
storage_map_[ctx] = slot;
|
||||
|
||||
ir::Value* init = nullptr;
|
||||
if (auto* init_value = decl.initValue()) {
|
||||
if (auto* init_value = ctx->initValue()) {
|
||||
if (!init_value->exp()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
||||
}
|
||||
init = GenExpr(*init_value->exp());
|
||||
init = EvalExpr(*init_value->exp());
|
||||
} else {
|
||||
init = builder_.CreateConstInt(0);
|
||||
}
|
||||
builder_.CreateStore(init, slot);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
|
||||
const SemanticContext& sema) {
|
||||
auto module = std::make_unique<ir::Module>();
|
||||
IRGenImpl gen(*module, sema);
|
||||
gen.Gen(tree);
|
||||
tree.accept(&gen);
|
||||
return module;
|
||||
}
|
||||
|
||||
@@ -6,39 +6,75 @@
|
||||
#include "ir/IR.h"
|
||||
#include "utils/Log.h"
|
||||
|
||||
ir::Value* IRGenImpl::GenExpr(SysYParser::ExpContext& expr) {
|
||||
if (auto* paren = dynamic_cast<SysYParser::ParenExpContext*>(&expr)) {
|
||||
return GenExpr(*paren->exp());
|
||||
}
|
||||
if (auto* number = dynamic_cast<SysYParser::NumberExpContext*>(&expr)) {
|
||||
if (!number->number() || !number->number()->ILITERAL()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量"));
|
||||
}
|
||||
return builder_.CreateConstInt(std::stoi(number->number()->getText()));
|
||||
}
|
||||
if (auto* var = dynamic_cast<SysYParser::VarExpContext*>(&expr)) {
|
||||
if (!var->var() || !var->var()->ID()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持普通整型变量"));
|
||||
}
|
||||
auto* decl = sema_.ResolveVarUse(var->var());
|
||||
if (!decl) {
|
||||
throw std::runtime_error(
|
||||
FormatError("irgen",
|
||||
"变量使用缺少语义绑定: " + var->var()->ID()->getText()));
|
||||
}
|
||||
auto it = storage_map_.find(decl);
|
||||
if (it == storage_map_.end()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("irgen",
|
||||
"变量声明缺少存储槽位: " + var->var()->ID()->getText()));
|
||||
}
|
||||
return builder_.CreateLoad(it->second, module_.GetContext().NextTemp());
|
||||
}
|
||||
if (auto* binary = dynamic_cast<SysYParser::AdditiveExpContext*>(&expr)) {
|
||||
ir::Value* lhs = GenExpr(*binary->exp(0));
|
||||
ir::Value* rhs = GenExpr(*binary->exp(1));
|
||||
return builder_.CreateBinary(ir::Opcode::Add, lhs, rhs,
|
||||
module_.GetContext().NextTemp());
|
||||
}
|
||||
throw std::runtime_error(FormatError("irgen", "暂不支持的表达式形式"));
|
||||
// 表达式生成当前也只实现了很小的一个子集。
|
||||
// 目前支持:
|
||||
// - 整数字面量
|
||||
// - 普通局部变量读取
|
||||
// - 括号表达式
|
||||
// - 二元加法
|
||||
//
|
||||
// 还未支持:
|
||||
// - 减乘除与一元运算
|
||||
// - 赋值表达式
|
||||
// - 函数调用
|
||||
// - 数组、指针、下标访问
|
||||
// - 条件与比较表达式
|
||||
// - ...
|
||||
ir::Value* IRGenImpl::EvalExpr(SysYParser::ExpContext& expr) {
|
||||
return std::any_cast<ir::Value*>(expr.accept(this));
|
||||
}
|
||||
|
||||
|
||||
std::any IRGenImpl::visitParenExp(SysYParser::ParenExpContext* ctx) {
|
||||
if (!ctx || !ctx->exp()) {
|
||||
throw std::runtime_error(FormatError("irgen", "非法括号表达式"));
|
||||
}
|
||||
return EvalExpr(*ctx->exp());
|
||||
}
|
||||
|
||||
|
||||
std::any IRGenImpl::visitNumberExp(SysYParser::NumberExpContext* ctx) {
|
||||
if (!ctx || !ctx->number() || !ctx->number()->ILITERAL()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持整数字面量"));
|
||||
}
|
||||
return static_cast<ir::Value*>(
|
||||
builder_.CreateConstInt(std::stoi(ctx->number()->getText())));
|
||||
}
|
||||
|
||||
// 变量使用的处理流程:
|
||||
// 1. 先通过语义分析结果把变量使用绑定回声明;
|
||||
// 2. 再通过 storage_map_ 找到该声明对应的栈槽位;
|
||||
// 3. 最后生成 load,把内存中的值读出来。
|
||||
//
|
||||
// 因此当前 IRGen 自己不再做名字查找,而是直接消费 Sema 的绑定结果。
|
||||
std::any IRGenImpl::visitVarExp(SysYParser::VarExpContext* ctx) {
|
||||
if (!ctx || !ctx->var() || !ctx->var()->ID()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持普通整型变量"));
|
||||
}
|
||||
auto* decl = sema_.ResolveVarUse(ctx->var());
|
||||
if (!decl) {
|
||||
throw std::runtime_error(
|
||||
FormatError("irgen",
|
||||
"变量使用缺少语义绑定: " + ctx->var()->ID()->getText()));
|
||||
}
|
||||
auto it = storage_map_.find(decl);
|
||||
if (it == storage_map_.end()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("irgen",
|
||||
"变量声明缺少存储槽位: " + ctx->var()->ID()->getText()));
|
||||
}
|
||||
return static_cast<ir::Value*>(
|
||||
builder_.CreateLoad(it->second, module_.GetContext().NextTemp()));
|
||||
}
|
||||
|
||||
|
||||
std::any IRGenImpl::visitAdditiveExp(SysYParser::AdditiveExpContext* ctx) {
|
||||
if (!ctx || !ctx->exp(0) || !ctx->exp(1)) {
|
||||
throw std::runtime_error(FormatError("irgen", "非法加法表达式"));
|
||||
}
|
||||
ir::Value* lhs = EvalExpr(*ctx->exp(0));
|
||||
ir::Value* rhs = EvalExpr(*ctx->exp(1));
|
||||
return static_cast<ir::Value*>(
|
||||
builder_.CreateBinary(ir::Opcode::Add, lhs, rhs,
|
||||
module_.GetContext().NextTemp()));
|
||||
}
|
||||
|
||||
@@ -27,32 +27,61 @@ IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
|
||||
func_(nullptr),
|
||||
builder_(module.GetContext(), nullptr) {}
|
||||
|
||||
void IRGenImpl::Gen(SysYParser::CompUnitContext& cu) {
|
||||
auto* func = cu.funcDef();
|
||||
if (func && func->ID() && func->ID()->getText() == "main") {
|
||||
GenFuncDef(*func);
|
||||
return;
|
||||
// 编译单元的 IR 生成当前只实现了最小功能:
|
||||
// - Module 已在 GenerateIR 中创建,这里只负责继续生成其中的内容;
|
||||
// - 当前会读取编译单元中的函数定义,并交给 visitFuncDef 生成函数 IR;
|
||||
//
|
||||
// 当前还没有实现:
|
||||
// - 多个函数定义的遍历与生成;
|
||||
// - 全局变量、全局常量的 IR 生成。
|
||||
std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
|
||||
}
|
||||
throw std::runtime_error(FormatError("irgen", "缺少 main 定义"));
|
||||
auto* func = ctx->funcDef();
|
||||
if (!func) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
|
||||
}
|
||||
func->accept(this);
|
||||
return {};
|
||||
}
|
||||
|
||||
void IRGenImpl::GenFuncDef(SysYParser::FuncDefContext& func) {
|
||||
if (!func.blockStmt()) {
|
||||
// 函数 IR 生成当前实现了:
|
||||
// 1. 获取函数名;
|
||||
// 2. 检查函数返回类型;
|
||||
// 3. 在 Module 中创建 Function;
|
||||
// 4. 将 builder 插入点设置到入口基本块;
|
||||
// 5. 继续生成函数体。
|
||||
//
|
||||
// 当前还没有实现:
|
||||
// - 通用函数返回类型处理;
|
||||
// - 形参列表遍历与参数类型收集;
|
||||
// - FunctionType 这样的函数类型对象;
|
||||
// - Argument/形式参数 IR 对象;
|
||||
// - 入口块中的参数初始化逻辑。
|
||||
// ...
|
||||
|
||||
// 因此这里目前只支持最小的“无参 int 函数”生成。
|
||||
std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
|
||||
}
|
||||
if (!ctx->blockStmt()) {
|
||||
throw std::runtime_error(FormatError("irgen", "函数体为空"));
|
||||
}
|
||||
if (!func.ID()) {
|
||||
if (!ctx->ID()) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
|
||||
}
|
||||
if (!func.funcType() || !func.funcType()->INT()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持 int main"));
|
||||
if (!ctx->funcType() || !ctx->funcType()->INT()) {
|
||||
throw std::runtime_error(FormatError("irgen", "当前仅支持无参 int 函数"));
|
||||
}
|
||||
|
||||
func_ = module_.CreateFunction(
|
||||
func.ID()->getText(), module_.GetContext().Int32());
|
||||
func_ = module_.CreateFunction(ctx->ID()->getText(), ir::Type::GetInt32Type());
|
||||
builder_.SetInsertPoint(func_->GetEntry());
|
||||
storage_map_.clear();
|
||||
|
||||
GenBlock(*func.blockStmt());
|
||||
ctx->blockStmt()->accept(this);
|
||||
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。
|
||||
VerifyFunctionStructure(*func_);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -6,18 +6,34 @@
|
||||
#include "ir/IR.h"
|
||||
#include "utils/Log.h"
|
||||
|
||||
bool IRGenImpl::GenStmt(SysYParser::StmtContext& stmt) {
|
||||
if (stmt.returnStmt()) {
|
||||
GenReturnStmt(*stmt.returnStmt());
|
||||
return true;
|
||||
// 语句生成当前只实现了最小子集。
|
||||
// 目前支持:
|
||||
// - return <exp>;
|
||||
//
|
||||
// 还未支持:
|
||||
// - 赋值语句
|
||||
// - if / while 等控制流
|
||||
// - 空语句、块语句嵌套分发之外的更多语句形态
|
||||
|
||||
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少语句"));
|
||||
}
|
||||
if (ctx->returnStmt()) {
|
||||
return ctx->returnStmt()->accept(this);
|
||||
}
|
||||
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
|
||||
}
|
||||
|
||||
void IRGenImpl::GenReturnStmt(SysYParser::ReturnStmtContext& ret) {
|
||||
if (!ret.exp()) {
|
||||
|
||||
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
|
||||
}
|
||||
if (!ctx->exp()) {
|
||||
throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
|
||||
}
|
||||
ir::Value* v = GenExpr(*ret.exp());
|
||||
ir::Value* v = EvalExpr(*ctx->exp());
|
||||
builder_.CreateRet(v);
|
||||
return BlockFlow::Terminated;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user