|
|
#include "irgen/IRGen.h"
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
#include "SysYParser.h"
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
std::string GetLValueName(SysYParser::LValueContext& lvalue) {
|
|
|
if (!lvalue.ID()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法左值"));
|
|
|
}
|
|
|
return lvalue.ID()->getText();
|
|
|
}
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
std::any IRGenImpl::visitBlockStmt(SysYParser::BlockStmtContext* ctx) {
|
|
|
if (!ctx) {
|
|
|
throw std::runtime_error(FormatError("irgen", "缺少语句块"));
|
|
|
}
|
|
|
for (auto* item : ctx->blockItem()) {
|
|
|
if (item) {
|
|
|
if (VisitBlockItemResult(*item) == BlockFlow::Terminated) {
|
|
|
// 当前语法要求 return 为块内最后一条语句;命中后可停止生成。
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
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 (ctx->decl()) {
|
|
|
ctx->decl()->accept(this);
|
|
|
return BlockFlow::Continue;
|
|
|
}
|
|
|
if (ctx->stmt()) {
|
|
|
return ctx->stmt()->accept(this);
|
|
|
}
|
|
|
throw std::runtime_error(FormatError("irgen", "暂不支持的语句或声明"));
|
|
|
}
|
|
|
|
|
|
// 变量声明的 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 = ctx->varDef();
|
|
|
if (!var_def) {
|
|
|
throw std::runtime_error(FormatError("irgen", "非法变量声明"));
|
|
|
}
|
|
|
var_def->accept(this);
|
|
|
return {};
|
|
|
}
|
|
|
|
|
|
|
|
|
// 当前仍是教学用的最小版本,因此这里只支持:
|
|
|
// - 局部 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(*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_[ctx] = slot;
|
|
|
|
|
|
ir::Value* init = nullptr;
|
|
|
if (auto* init_value = ctx->initValue()) {
|
|
|
if (!init_value->exp()) {
|
|
|
throw std::runtime_error(FormatError("irgen", "当前不支持聚合初始化"));
|
|
|
}
|
|
|
init = EvalExpr(*init_value->exp());
|
|
|
} else {
|
|
|
init = builder_.CreateConstInt(0);
|
|
|
}
|
|
|
builder_.CreateStore(init, slot);
|
|
|
return {};
|
|
|
}
|