我先快速读取当前 IRGen 的入口与表达式/语句文件,然后按“节点到接口调用映射”给你一份可以直接交给 IRGen 同学实现的调用说明。 Read [](file:///home/shrink/nudt-compiler-cpp/include/ir/IR.h#320-320), lines 320 to 387 Read [](file:///home/shrink/nudt-compiler-cpp/include/irgen/IRGen.h) Read [](file:///home/shrink/nudt-compiler-cpp/src/irgen/IRGenExp.cpp) Read [](file:///home/shrink/nudt-compiler-cpp/src/irgen/IRGenStmt.cpp) Read [](file:///home/shrink/nudt-compiler-cpp/src/irgen/IRGenFunc.cpp) 可以,下面给你一份面向 IRGen 同学的“如何调用你新增 IR 接口”的实现说明,按落地顺序写。 先看调用边界 1. IRGen 只负责把语法树翻译成 IR,不做符号查找 变量和函数绑定依赖 Sema 结果,参考 IRGenExp.cpp 的变量读取流程。 2. 所有指令创建都通过 IRBuilder 新增接口定义在 IR.h。 3. 终结指令规则必须遵守 Ret/Br/CondBr 一旦插入当前块,这个块不能再插普通指令,规则在 Instruction.cpp 和 BasicBlock.cpp。 建议 IRGen 调用映射 一、表达式层 1. 加减乘除模 - a + b: CreateAdd(lhs, rhs, temp) - a - b: CreateSub(lhs, rhs, temp) - a * b: CreateMul(lhs, rhs, temp) - a / b: CreateDiv(lhs, rhs, temp) - a % b: CreateMod(lhs, rhs, temp) 2. 比较表达式 - == != < <= > >= 统一走 CreateCmp(op, lhs, rhs, temp) - 返回 i32,约定 0 为假,非 0 为真 3. 一元运算建议 - -x: CreateSub(const0, x, temp) - !x: CreateCmp(Eq, x, const0, temp) - +x: 直接返回 x 4. 变量读取和赋值 - 读取: 先由 Sema 绑定 use 到 decl,再从 storage_map 找槽位,CreateLoad - 赋值: EvalExpr(rhs) 后对槽位 CreateStore(rhs_val, slot) 对应修改文件: - IRGenExp.cpp - IRGenDecl.cpp - IRGenStmt.cpp 二、控制流层 1. if/else - 创建三个块: then, else, merge - cond = EvalExpr(condExp) - 当前块插 CreateCondBr(cond, then, else) - 切入 then 块生成语句,末尾若未终结则 CreateBr(merge) - 切入 else 块同理 - 最后 SetInsertPoint(merge) 2. while - 创建三个块: cond, body, exit - 进入前先 CreateBr(cond) - cond 块计算条件,CreateCondBr(cond_val, body, exit) - body 块生成循环体,若未终结则回跳 CreateBr(cond) - 最后 SetInsertPoint(exit) 3. break/continue - IRGen 维护循环栈,每层保存 continue_target 和 break_target - break 直接 CreateBr(break_target) - continue 直接 CreateBr(continue_target) 对应修改文件: - IRGenStmt.cpp 三、函数与调用层 1. 函数定义 - 用 Module.CreateFunction(name, ret_type, param_types) 建函数 - 入口块 SetInsertPoint(entry) - 形参落栈策略建议:每个参数先 alloca,再 store 到本地槽位,后续统一按 load/store 访问 2. 函数调用 - 先拿到 callee 对应的 Function - 实参逐个 EvalExpr 得到 args - 调用 CreateCall(callee, args, temp) - 若返回值非 void,把返回 Value 继续参与表达式计算 对应修改文件: - IRGenFunc.cpp - IRGenExp.cpp 四、你要提醒 IRGen 同学的两个关键点 1. 插入点管理 每次生成 Br/CondBr/Ret 后,必须切换到新块再继续生成。否则会触发块已终结错误。 2. grammar 上下文名先对齐 你们当前 IRGen 里还在用 ParenExpContext、AdditiveExpContext 这类命名,实际 grammar 是另一套层级时要先改 Visitor 入口,否则接口再全也接不上。可先核对 SysY.g4 与 IRGen.h。 最小接入顺序 1. 先接表达式算术与比较(M1) 2. 再接 if/while/break/continue(M3) 3. 再接函数参数和调用(M2) 如果你要,我下一步可以给你一版“按当前 grammar 的具体 visitor 函数名”逐条对照表,IRGen 同学可以直接照着改函数签名和调用点。