alloca本质是栈帧内动态分配内存并返回指针,非变量声明;必须配合store/load使用,且须位于函数入口基本块,类型参数决定分配空间大小,align建议显式指定。

alloca 指令本质是栈帧分配,不是“声明变量”
alloca 不像 C 的 int x; 那样定义语义上的变量,它只在函数栈帧上动态分配一块内存,并返回该内存的地址(即指针类型值)。LLVM IR 中没有“变量作用域”或“生命周期管理”,只有显式的 alloca → store → load 链路。
常见错误现象:%x = alloca i32 后直接用 %x 当整数参与 add,会报错 “invalid operand type”——因为 %x 是 i32*,不是 i32。
- 必须搭配
store写入值、load读出值 - 分配位置在函数入口基本块(
entry)最安全;若在循环内重复alloca,每次都会压栈,可能栈溢出 -
align参数建议显式指定(如align 4),否则依赖 target datalayout,默认对齐可能不满足访问要求
alloca 的类型参数决定分配单元大小
alloca 的第一个参数是所分配内存的元素类型,不是“变量类型”。比如 %p = alloca [4 x i32] 分配的是 16 字节连续空间(4 个 i32),而 %q = alloca i32 只分配 4 字节。两者都返回对应类型的指针([4 x i32]* 或 i32*)。
使用场景差异:
- 标量局部变量:用
alloca i32、alloca double等 - 数组或结构体:用
alloca [N x T]或alloca %struct.foo,后续需配合getelementptr计算偏移 - 避免误用
alloca i32*:这分配的是“指向 i32 的指针”的存储空间(即 8 字节存一个地址),不是“存 i32 的空间”
alloca 必须在函数内、且不能出现在 PHI 节点之后
LLVM IR 要求所有 alloca 指令必须位于函数的首个基本块(通常是 entry),或至少在任何控制流汇合点(如 phi 指令所在位置)之前。否则 verifier 会报错:"alloca must appear in first block" 或 "PHI node not in first block"。
原因在于:栈帧布局需在函数入口就确定,不能随分支动态变化。即使你写 if 分支里各放一个 alloca,LLVM 也不允许——它不等价于 C 的变长数组(VLA),后者由 runtime 处理。
- 若需条件分配,应提前在
entry块分配足够空间,再用条件逻辑控制store/load - IRBuilder 中调用
builder.CreateAlloca(...)时,确保builder的插入点(insert point)在 entry 块内 - 多个
alloca在同一块中顺序执行,地址高低取决于分配顺序和对齐填充,不可假设物理相邻
alloca 和 SSA 形式天然冲突,所以必须靠 load/store 衔接
LLVM IR 是静态单赋值(SSA)形式,但栈内存本身是非 SSA 的——你可以反复 store 到同一地址。因此 alloca 是 IR 中少数打破 SSA 纯度的机制之一,它把“可变状态”引入了 otherwise-functional IR。
这意味着:不能指望 %x = alloca i32 后直接拿 %x 当值用;所有读写都必须经由指针解引用。
- 错误写法:
%y = add i32 %x, 1(%x 是 i32*) - 正确链路:
%addr = alloca i32→store i32 42, i32* %addr→%val = load i32, i32* %addr→%z = add i32 %val, 1 - 性能影响:频繁
load/store可能阻碍优化;现代 LLVM 通常能将简单栈变量提升为寄存器(via mem2reg pass),但前提是无指针逃逸
实际写 IR 或用 IRBuilder 时,最容易被忽略的是:alloca 返回的是地址,而后续所有数据操作都默认面向值。这个“指针 vs 值”的切换点,是初学者卡住最多的地方。











