后端Pass简介——MachineFrameInfo
MachineFrameInfo
这是属于 CodeGen 的一个子文件,暂且把他认定为 Pass。他实现的是“栈帧布局和栈内对象管理相关的核心模块”。是 LLVM 用于管理函数栈帧中所有栈上对象(如局部变量、Spill槽、调用帧等)的位置、对齐和属性的模块,并辅助生成正确的栈布局与栈帧大小。
概念 | 简要说明 |
---|---|
栈帧(Stack Frame) | 每个函数调用分配的一块栈内存,用于保存局部变量、返回地址、保存的寄存器等 |
对齐(Alignment) | 指定内存对象在栈上的对齐要求,通常是 4/8/16 字节 |
Spill Slot | 当寄存器不够用时,变量会被“溢出”到栈上,称为 Spill |
可变大小对象 | 如 alloca 分配的大小运行时决定的数组 |
固定栈对象(Fixed Object) | 位于栈帧固定位置的对象,如返回地址、保存寄存器 |
StackRealignable | 当前目标是否允许动态栈对齐 |
Call Frame Size | 为函数调用参数保留的栈空间 |
Frame Pointer / Stack Pointer | 栈帧地址计算常用寄存器,影响对象定位 |
因为是重点工具函数集合,所以这边直接讲每个函数在干什么 |
① CreateStackObject(uint64_t Size, Align Alignment, …)
这个函数用于创建一个普通的局部栈对象,也可以是 spill 对象(由寄存器溢出产生)。它会执行以下操作:
- 对齐检查:如果目标平台不支持栈实对齐(StackRealignable = false),将强制限制对齐大小;
- 将对象信息(大小、对齐、是否Spill、是否可变等)压入 Objects 向量;
- 更新最大对齐要求 MaxAlignment;
- 返回对象的 FrameIndex,供后续访问使用。
② CreateSpillStackObject(uint64_t Size, Align Alignment)
专门用于为寄存器溢出创建栈空间(Spill Slot)。内部调用上面的 CreateStackObject,设置 IsSpillSlot = true。
其本质和局部变量没太大差别,但在寄存器分配失败时自动调用。
③ CreateVariableSizedObject(Align Alignment, const AllocaInst *Alloca)
用于处理运行时才确定大小的变量(例如 alloca 分配的数组)。其行为是: - 标记当前函数含有可变栈对象:HasVarSizedObjects = true;
- 由于大小不确定,设置 Size = 0;
- 依然要设置对齐要求,并更新最大对齐;
- 会影响后续是否使用 Frame Pointer,以及栈帧如何对齐。
④ CreateFixedObject(uint64_t Size, int64_t SPOffset, …)
这个函数创建一个固定位置的栈对象。它主要用于处理函数调用约定中ABI保留的栈空间,如返回地址、保存的寄存器等。
特点是: - 必须传入一个固定偏移 SPOffset;
- 对齐方式由偏移值和栈对齐策略推导出来;
- 这些对象被插入在 Objects 的最前面,编号为负数(FixedObject index);
- 通常在函数开始就确定,不随后续变量变化。
⑤ CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, bool IsImmutable)
和上面的 CreateFixedObject 类似,只不过专门用于创建固定位置的 Spill 对象。
如:某些平台对特定寄存器要求必须保存到特定位置。
⑥ estimateStackSize(const MachineFunction &MF)
这个函数用于估算当前函数的总栈帧大小,具体包括: - 累加所有非固定、未死亡的栈对象的大小;
- 每次增加时按对象的对齐要求进行对齐(alignTo);
- 考虑是否需要保留调用帧空间(Call Frame);
- 最终将总大小对齐到全局 StackAlignment 或 TransientStackAlignment;
- 如果有 FramePointer 被消除,还需保证对齐到最大对齐要求。
这是生成目标代码时确定函数栈帧边界的核心函数之一。
⑦ getPristineRegs(const MachineFunction &MF)
返回一个 BitVector,表示当前函数中哪些物理寄存器没有被破坏(即“干净的”)。
流程如下: - 遍历所有 Callee-Saved 寄存器;
- 把真正被使用(并保存)的寄存器剔除掉;
- 结果就是可以复用或省略保存的寄存器集合。
评论