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.

131 lines
4.5 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 <stdexcept>
#include <string>
#include "SysYParser.h"
#include "ir/IR.h"
#include "sem/func.h"
#include "utils/Log.h"
// 辅助:求值表达式为整数(用于数组维度)
static int EvalExprInt(SysYParser::ExpContext* ctx) {
if (!ctx) return 0;
try {
auto cv = sem::EvaluateExp(*ctx->addExp());
return static_cast<int>(cv.int_val);
} catch (...) {
return 0;
}
}
// ─── 构造函数 ─────────────────────────────────────────────────────────────────
IRGenImpl::IRGenImpl(ir::Module& module, const SemanticContext& sema)
: module_(module),
sema_(sema),
func_(nullptr),
builder_(module.GetContext(), nullptr) {}
// ─── visitCompUnit ────────────────────────────────────────────────────────────
std::any IRGenImpl::visitCompUnit(SysYParser::CompUnitContext* ctx) {
if (!ctx) {
throw std::runtime_error(FormatError("irgen", "缺少编译单元"));
}
// 先处理全局声明
in_global_scope_ = true;
for (auto* decl : ctx->decl()) {
if (decl) decl->accept(this);
}
in_global_scope_ = false;
// 再生成函数
for (auto* funcDef : ctx->funcDef()) {
if (funcDef) funcDef->accept(this);
}
return {};
}
// ─── visitFuncDef ─────────────────────────────────────────────────────────────
std::any IRGenImpl::visitFuncDef(SysYParser::FuncDefContext* ctx) {
if (!ctx || !ctx->Ident()) {
throw std::runtime_error(FormatError("irgen", "缺少函数定义或函数名"));
}
if (!ctx->block()) {
throw std::runtime_error(FormatError("irgen", "函数体为空"));
}
std::string func_name = ctx->Ident()->getText();
// 确定返回类型
std::shared_ptr<ir::Type> ret_type;
if (!ctx->funcType()) {
throw std::runtime_error(FormatError("irgen", "缺少函数返回类型"));
}
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::GetFloat32Type();
} else {
throw std::runtime_error(
FormatError("irgen", "函数 " + func_name + " 返回类型不支持"));
}
func_ = module_.CreateFunction(func_name, ret_type);
storage_map_.clear();
// 设置插入点到入口块
builder_.SetInsertPoint(func_->GetEntry());
// 处理参数
if (ctx->funcFParams()) {
for (auto* param : ctx->funcFParams()->funcFParam()) {
if (!param || !param->Ident()) continue;
std::string pname = param->Ident()->getText();
bool is_float = param->bType() && param->bType()->Float();
bool is_array_param = !param->L_BRAKT().empty();
if (is_array_param) {
// 数组参数:传递为指针
auto ptr_type = is_float ? ir::Type::GetPtrFloat32Type() : ir::Type::GetPtrInt32Type();
ir::Argument* arg = func_->AddArgument(ptr_type, pname);
storage_map_[param] = arg;
// 记录维度信息(第一维未知,后续维度从 exp 中获取)
std::vector<int> dims;
dims.push_back(-1); // 第一维未知
for (auto* exp_ctx : param->exp()) {
dims.push_back(EvalExprInt(exp_ctx));
}
array_dims_[param] = dims; // 始终记录,包括一维数组参数
} else {
// 标量参数
auto arg_type = is_float ? ir::Type::GetFloat32Type() : ir::Type::GetInt32Type();
ir::Argument* arg = func_->AddArgument(arg_type, pname);
auto* slot = is_float ? builder_.CreateAllocaF32(pname + ".addr")
: builder_.CreateAllocaI32(pname + ".addr");
storage_map_[param] = slot;
builder_.CreateStore(arg, slot);
}
}
}
// 生成函数体
ctx->block()->accept(this);
// 若最后一个基本块没有 terminator自动补 ret
auto* last_bb = builder_.GetInsertBlock();
if (last_bb && !last_bb->HasTerminator()) {
if (ret_type->IsVoid()) {
builder_.CreateRetVoid();
} else if (ret_type->IsFloat32()) {
builder_.CreateRet(builder_.CreateConstFloat(0.0f));
} else {
builder_.CreateRet(builder_.CreateConstInt(0));
}
}
return {};
}