|
|
#include "irgen/IRGen.h"
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
#include "SysYParser.h"
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
void VerifyFunctionStructure(const ir::Function& func) {
|
|
|
// 当前 IRGen 仍是单入口、顺序生成;这里在生成结束后补一层块终结校验。
|
|
|
for (const auto& bb : func.GetBlocks()) {
|
|
|
if (!bb || !bb->HasTerminator()) {
|
|
|
throw std::runtime_error(
|
|
|
FormatError("irgen", "基本块未正确终结: " +
|
|
|
(bb ? bb->GetName() : std::string("<null>"))));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
|
|
|
: module_(module),
|
|
|
sema_(sema),
|
|
|
func_(nullptr),
|
|
|
builder_(module.GetContext(), nullptr) {}
|
|
|
|
|
|
// 编译单元的 IR 生成当前只实现了最小功能:
|
|
|
// - Module 已在 GenerateIR 中创建,这里只负责继续生成其中的内容;
|
|
|
// - 当前会读取编译单元中的函数定义,并交给 visitFuncDef 生成函数 IR;
|
|
|
//
|
|
|
// 当前还没有实现:
|
|
|
// - 多个函数定义的遍历与生成;
|
|
|
// - 全局变量、全局常量的 IR 生成。
|
|
|
std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
|
|
|
}
|
|
|
auto* func = ctx->funcDef();
|
|
|
if (!func) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
|
|
|
}
|
|
|
func->accept(this);
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
// 函数 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 (!ctx->ID()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
|
|
|
}
|
|
|
if (!ctx->funcType() || !ctx->funcType()->INT()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "当前仅支持无参 int 函数"));
|
|
|
}
|
|
|
|
|
|
func_ = module_.CreateFunction(ctx->ID()->getText(), ir::Type::GetInt32Type());
|
|
|
builder_.SetInsertPoint(func_->GetEntry());
|
|
|
storage_map_.clear();
|
|
|
|
|
|
ctx->blockStmt()->accept(this);
|
|
|
// 语义正确性主要由 sema 保证,这里只兜底检查 IR 结构是否合法。
|
|
|
VerifyFunctionStructure(*func_);
|
|
|
return {};
|
|
|
}
|