irbuilder插入点必须设在basicblock内部且不能位于terminator之后,basicblock须已挂载到function且function已加入module,多次setinsertpoint会覆盖旧位置,推荐用createentryblockforfunction设函数入口插入点。

IRBuilder 插入点必须设在 BasicBlock 内部,不能悬空或指向 terminator
IRBuilder 的插入点(insertion point)本质是「下一条指令将被插入的位置」,它必须落在某个 BasicBlock 的指令序列中,且不能放在终结指令(terminator)之后。一旦插入点无效,后续调用 builder.CreateAdd() 等方法会触发断言失败或产生未定义行为。
常见错误现象包括:Assertion failed: getInsertBlock() && "Cannot create instructions outside a basic block!" 或生成的 IR 出现指令顺序错乱、跳转目标丢失。
- 插入点可以设在任意非 terminator 指令之前(含
begin()),例如builder.SetInsertPoint(&*bb.begin()) - 不能设在 terminator 之后:即使你用
++it越过 terminator,SetInsertPoint(bb, it)也会失效 - 若 BasicBlock 为空,必须先确保它已关联到 Function(即
bb->getParent() != nullptr),否则builder.insert()会静默失败
设置插入点前必须确保 BasicBlock 已插入 Function
BasicBlock 不是独立存在的——它必须属于某个 Function,且该 Function 必须已注册进 Module。否则,即使你调用了 builder.SetInsertPoint(bb),生成的指令也不会出现在 IR 中,也不会报错,只是「消失」。
典型误操作:构造完 bb = BasicBlock::Create(ctx, "entry", func) 后,直接 builder.SetInsertPoint(bb) 并开始生成指令,但忘了 func 还没加进 module(比如漏了 module->getFunctionList().push_back(func) 或等价逻辑)。
- 安全做法:用三参数构造
BasicBlock::Create(ctx, "entry", func, insertBeforeBB),此时 block 自动挂载 - 或者显式调用
func->getBasicBlockList().push_back(bb),再设插入点 - 检查手段:打印
bb->getParent()和func->getParent(),二者都应非空
多次 SetInsertPoint 会覆盖旧位置,不自动推进
IRBuilder 不维护「当前指令游标」的自动递进逻辑。每次调用 builder.CreateAdd() 后,插入点仍停留在原位置;下次调用仍会把新指令插在同一个地方,导致指令堆叠、覆盖控制流。
这在循环生成指令时尤其危险,比如想为每个参数生成一条 load,却忘了移动插入点,结果所有 load 都挤在第一行后面,后续指令全部错位。
- 手动推进方式:获取刚创建的指令指针,再用
builder.SetInsertPoint(inst->getNextNode()) - 更稳妥的方式:在循环内每次都重新定位,例如
builder.SetInsertPoint(bb, bb->getTerminator())插到末尾 - 注意
bb->getTerminator()可能为nullptr(block 无 terminator),此时需用bb->end()
函数入口插入点推荐用 CreateEntryBlockForFunction
对函数首块(entry block)设插入点,不要手写 BasicBlock::Create(...) + SetInsertPoint 组合。LLVM 提供了更健壮的封装:IRBuilder::CreateEntryBlockForFunction()(实际是 Function::CreateEntryBlockForFunction 的配套用法)。
它会自动处理三件事:分配 block、插入到 function 开头、设置好 PHI 节点预留位(如果需要)、并返回可安全使用的插入点。省去手动管理 parent、terminator、phi placement 的琐碎细节。
- 适用场景:生成函数 prologue、参数提取、局部变量 alloca
- 不适用场景:向已有 block 中间插入(如插桩、patch),此时仍需手动
SetInsertPoint - 容易被忽略的点:entry block 的第一个指令必须是
alloca(按 LLVM ABI),否则后端可能崩溃或优化异常
SetInsertPoint 调用,背后连着三条链:block → function → module,缺一不可。











