llvm生成if-else需创建entry/then/else三个基本块,entry中用icmp比较后createcondbr跳转,then/else末尾须有终结指令,合并分支值需phinode且入边数与前驱块数严格一致。

LLVM 生成 if 语句的控制流,核心是用基本块(BasicBlock)+ 条件分支指令(br i1 %cond, label %then, label %else)+ 比较指令(icmp)三者配合完成。它不直接翻译成“跳转到某行”,而是构造显式的、带标签的控制流图(CFG),每个分支必须落在独立的基本块里。
怎么写 IRBuilder 代码生成 if-else 的基础结构
用 IRBuilder 构建 if 流程时,不能只调一条 CreateCondBr 就完事——必须提前创建好三个基本块:entry(入口)、then、else,再把控制流连起来:
-
entry块里放条件计算(如icmp slt i32 %a, %b)和条件跳转(CreateCondBr) -
then和else块必须各自以终结指令结尾(br或ret),否则 verifier 会报错"Basic block must end with terminator instruction" - 跳转目标块必须已插入函数(
Function::getBasicBlockList().push_back()或用BasicBlock::Create(..., &F)绑定) - 如果
then和else都要返回值(比如if是表达式),得用PHINode合并两个分支的输出,否则类型检查失败
为什么 icmp 的比较类型(slt/ult/eq)容易出错
icmp 的签名决定结果语义,选错会导致逻辑翻转或未定义行为:
- 整数比较默认按有符号处理:
icmp slt i32 %x, 0判断x是否为负;若x实际是无符号数(如size_t),该判断失效 - C 语言中
a 对无符号变量应译为 <code>icmp ult,不是slt;误用slt可能让高位为 1 的数被当成负数,条件恒真或恒假 -
icmp eq和icmp ne无符号/有符号等价,但其他比较符必须匹配原始类型,否则后端优化可能删掉整个分支
为什么 br 指令后必须显式跳转到 merge 块
LLVM IR 要求函数控制流必须收敛——then 和 else 分支不能各自 ret(除非是末尾分支),否则无法统一返回值或继续执行后续逻辑:
- 典型做法是加第四个块:
merge,让then和else都br label %merge -
merge块开头插入PHINode,接收来自两个前驱块的值,例如:%result = phi i32 [ %then_val, %then ], [ %else_val, %else ] - 漏掉
merge块或没设PHINode,会导致后续使用该值时报错"Use of undefined value"或 verifier 拒绝验证
常见错误:忘记设置 Builder 插入点(InsertPoint)
IRBuilder 是状态机,所有生成的指令都插在当前 InsertPoint 位置。切换基本块后不调 SetInsertPoint,指令会错插到上一个块末尾:
- 在
entry块调完CreateCondBr后,必须立刻Builder->SetInsertPoint(thenBB),再写then逻辑 - 同理,进
else块前也要重设;进merge块前同样要设 - 错误示例:没设点就写
CreateAdd,结果指令出现在br指令之后——这违反了基本块终结指令必须在末尾的规则
最易被忽略的是 PHINode 的入边数量与前驱块数量必须严格一致,且每个前驱块只能贡献一个值;少一条 addIncoming 或多传一个块,verifier 直接拒绝生成 bitcode。











