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