|
|
#include "irgen/IRGen.h"
|
|
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
#include "SysYParser.h"
|
|
|
#include "ir/IR.h"
|
|
|
#include "utils/Log.h"
|
|
|
|
|
|
// 表达式生成当前也只实现了很小的一个子集。
|
|
|
// 目前支持:
|
|
|
// - 整数字面量
|
|
|
// - 普通局部变量读取
|
|
|
// - 括号表达式
|
|
|
// - 二元加法
|
|
|
//
|
|
|
// 还未支持:
|
|
|
// - 减乘除与一元运算
|
|
|
// - 赋值表达式
|
|
|
// - 函数调用
|
|
|
// - 数组、指针、下标访问
|
|
|
// - 条件与比较表达式
|
|
|
// - ...
|
|
|
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()));
|
|
|
}
|