You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

207 lines
6.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "irgen/IRGen.h"
#include <memory>
#include <stdexcept>
#include <vector>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
namespace {
void VerifyFunctionStructure(const ir::Function& func) {
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) {}
// 修正:没有 mainFuncDef通过函数名找到 main
std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
std::cout << "[DEBUG IRGEN] visitCompUnit" << std::endl;
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
}
// 处理全局变量声明
for (auto* decl : ctx->decl()) {
if (decl) {
decl->accept(this);
}
}
// 处理所有函数定义
for (auto* funcDef : ctx->funcDef()) {
if (funcDef) {
funcDef->accept(this);
}
}
return {};
}
std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
std::cout << "[DEBUG IRGEN] visitFuncDef: " << (ctx && ctx->Ident() ? ctx->Ident()->getText() : "<null>") << std::endl;
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义"));
}
if (!ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "缺少函数名"));
}
std::string funcName = ctx->Ident()->getText();
if (!ctx->block()) {
throw std::runtime_error(FormatError("irgen", "函数体为空"));
}
std::shared_ptr<ir::Type> ret_type = ir::Type::GetInt32Type();
if (ctx->funcType()) {
if (ctx->funcType()->Void()) {
ret_type = ir::Type::GetVoidType();
} else if (ctx->funcType()->Int()) {
ret_type = ir::Type::GetInt32Type();
} else if (ctx->funcType()->Float()) {
ret_type = ir::Type::GetFloatType();
}
}
std::vector<std::shared_ptr<ir::Type>> param_types;
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->bType()) continue;
std::shared_ptr<ir::Type> param_ty;
if (param->bType()->Int()) {
param_ty = ir::Type::GetInt32Type();
} else if (param->bType()->Float()) {
param_ty = ir::Type::GetFloatType();
} else {
param_ty = ir::Type::GetInt32Type();
}
if (!param->L_BRACK().empty()) {
if (param_ty->IsInt32()) {
param_ty = ir::Type::GetPtrInt32Type();
} else if (param_ty->IsFloat()) {
param_ty = ir::Type::GetPtrFloatType();
}
}
param_types.push_back(param_ty);
}
}
auto func_type = ir::Type::GetFunctionType(ret_type, param_types);
func_ = module_.CreateFunction(funcName, func_type);
builder_.SetInsertPoint(func_->GetEntry());
storage_map_.clear();
param_map_.clear();
// 函数参数 (按照语义分析、symbol table 定义顺序)
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->Ident()) continue;
std::string name = param->Ident()->getText();
std::shared_ptr<ir::Type> param_ty;
if (param->bType()->Int()) {
param_ty = ir::Type::GetInt32Type();
} else if (param->bType()->Float()) {
param_ty = ir::Type::GetFloatType();
} else {
param_ty = ir::Type::GetInt32Type();
}
if (!param->L_BRACK().empty()) {
if (param_ty->IsInt32()) {
param_ty = ir::Type::GetPtrInt32Type();
} else if (param_ty->IsFloat()) {
param_ty = ir::Type::GetPtrFloatType();
}
}
auto* arg = func_->AddArgument(std::make_unique<ir::Argument>(param_ty, name));
ir::AllocaInst* slot;
if (param_ty->IsInt32() || param_ty->IsPtrInt32()) {
slot = builder_.CreateAllocaI32(module_.GetContext().NextTemp());
} else if (param_ty->IsFloat() || param_ty->IsPtrFloat()) {
slot = builder_.CreateAllocaFloat(module_.GetContext().NextTemp());
} else {
throw std::runtime_error(FormatError("irgen", "不支持的参数类型"));
}
builder_.CreateStore(arg, slot);
param_map_[name] = slot;
}
}
// 生成函数体
ctx->block()->accept(this);
if (!func_->GetEntry()->HasTerminator()) {
auto retVal = builder_.CreateConstInt(0);
builder_.CreateRet(retVal);
}
VerifyFunctionStructure(*func_);
func_ = nullptr;
return {};
}
std::any IRGenImpl::visitBlock(SysYParser::BlockContext* ctx) {
std::cout << "[DEBUG IRGEN] visitBlock: " << (ctx ? ctx->getText() : "<null>") << std::endl;
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
}
BlockFlow flow = BlockFlow::Continue;
for (auto* item : ctx->blockItem()) {
if (!item) continue;
flow = VisitBlockItemResult(*item);
if (flow == BlockFlow::Terminated) {
break;
}
auto* cur = builder_.GetInsertBlock();
std::cout << "[DEBUG] current insert block: "
<< (cur ? cur->GetName() : "<null>") << std::endl;
if (cur && cur->HasTerminator()) {
break;
}
}
return flow;
}
// 类型安全的包装器
IRGenImpl::BlockFlow IRGenImpl::VisitBlockItemResult(
SysYParser::BlockItemContext& item) {
auto result = item.accept(this);// 调用 visitBlockItem返回 std::any 包装的 BlockFlow
return std::any_cast<BlockFlow>(result); // 解包为 BlockFlow
}
// 用于遍历块内项,返回是否继续访问后续项(如遇到 return/break/continue 则终止访问)
std::any IRGenImpl::visitBlockItem(SysYParser::BlockItemContext* ctx) {
std::cout << "[DEBUG IRGEN] visitBlockItem: " << (ctx ? ctx->getText() : "<null>") << std::endl;
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少块内项"));
}
// 块内项可以是语句或声明,优先处理语句(如 return/break/continue 可能终止块内执行)
if (ctx->stmt()) {
return ctx->stmt()->accept(this); // 语句访问返回 BlockFlow指示是否继续访问后续项
}
// 处理声明(如变量定义),继续访问后续项
if (ctx->decl()) {
ctx->decl()->accept(this);
return BlockFlow::Continue; // 声明不会终止块内执行,继续访问后续项
}
throw std::runtime_error(FormatError("irgen", "暂不支持的块内项"));
}