CallingConv.td文件的作用是什么
定义调用约定(Calling Convention)的文件,主要作用包括:
寄存器保存规则定义:
明确规定了在不同调用约定下,哪些寄存器是被调用者必须保存的
这对于函数调用时的寄存器使用和保存至关重要
支持多种调用约定
支持纯整数、单精度浮点、双精度浮点等多种调用约定
为不同场景提供合适的寄存器保存策略
中断处理支持
为中断处理程序定义了特殊的寄存器保存规则
确保中断处理程序能够正确保存和恢复所有可能使用的寄存器
编译器后端支持
这些定义被 LLVM 后端用来生成正确的函数调用代码
影响寄存器分配、函数序言(prologue)和尾声(epilogue)的生成
CallingConv.td文件的构成是什么
- 基本调用约定定义
调用约定实际上是在 RISCVISelLowering.cpp 中通过 CC_RISCV 函数以自定义代码实现的。这个 td 文件主要定义了被调用者保存寄存器(Callee Saved Registers)的规则。 - 被调用者保存寄存器定义
CSR_ILP32_LP64:
: CalleeSavedRegs<(add X1, X3, X4, X8, X9, (sequence "X%u", 18, 27))>;
- 定义了基础整数调用约定的被调用者保存寄存器
- 包括:X1(返回地址)、X3-X4(gp/sp)、X8-X9(s0-s1)、X18-X27(s2-s11)
- 适用于 ILP32(32位)和 LP64(64位)两种整数调用约定
CSR_ILP32F_LP64F:
: CalleeSavedRegs<(add CSR_ILP32_LP64,
F8_F, F9_F, (sequence "F%u_F", 18, 27))>;
- 在基础整数寄存器之上添加了单精度浮点寄存器
- 包括:F8-F9(fs0-fs1)、F18-F27(fs2-fs11)
- 适用于 ILP32F 和 LP64F 调用约定
CSR_ILP32D_LP64D:
: CalleeSavedRegs<(add CSR_ILP32_LP64,
F8_D, F9_D, (sequence "F%u_D", 18, 27))>;
- 在基础整数寄存器之上添加了双精度浮点寄存器
- 寄存器编号与单精度版本相同,但类型为双精度
- 适用于 ILP32D 和 LP64D 调用约定
- 特殊场景定义
CSR_NoRegs
def CSR_NoRegs : CalleeSavedRegs<(add)>;
- 定义了一个空的被调用者保存寄存器集合
- 用于 RISCVRegisterInfo::getNoPreservedMask() 的实现
CSR_Interrupt
def CSR_Interrupt : CalleeSavedRegs<(add X1,
(sequence "X%u", 3, 9),
(sequence "X%u", 10, 11),
...
- 定义了中断处理程序需要保存/恢复的寄存器
- 包含了所有通用寄存器(X1-X31),因为中断处理程序需要保存所有使用的寄存器
CSR_XLEN_F32_Interrupt 和 CSR_XLEN_F64_Interrupt
- 类似于 CSR_Interrupt,但分别包含了所有32位和64位浮点寄存器
- 用于支持浮点运算的中断处理程序
CalleeSavedRegs 的详细解释
用于定义被调用者保存寄存器(Callee-Saved Registers)的集合。在函数调用约定中,这些寄存器由被调用函数负责保存和恢复,如果被调用函数要使用这些寄存器,必须在函数开始时保存它们的值,并在函数返回前恢复。
CalleeSavedRegs 的基本原型是:
class CalleeSavedRegs<list<Register> regs> {
list<Register> CalleeSavedRegs = regs;
}
- regs: 一个寄存器列表,包含所有需要被调用者保存的寄存器
- 寄存器可以通过以下方式指定:
- 直接指定:如 X1, X3 等
- 使用 add 操作符合并多个寄存器或寄存器序列
- 使用 sequence 生成连续的寄存器序列
CCIfType:根据参数类型应用特定动作的条件类。
CCIfType<[i32, f32], CCAssignToReg<[SGPR0, SGPR1]>>
表示如果参数是 i32 或 f32 类型,则分配到 SGPR0 或 SGPR1。
CCIfExtend:当参数需要符号扩展或零扩展时应用特定动作的条件类。
CCIfType<[i16], CCIfExtend<CCPromoteToType<i32>>>
表示如果参数是 i16 类型,先扩展再提升为 i32。
CCPromoteToType:将参数类型提升为指定类型的动作类。
CCIfType<[i1], CCPromoteToType<i32>>
表示将 i1 类型提升为 i32。
CCAssignToReg:
将参数分配到指定寄存器的动作类。
CCAssignToReg<[SGPR0, SGPR1, SGPR2]>
表示将参数分配到 SGPR0、SGPR1 或 SGPR2。
CCIfInReg:当参数标记为在寄存器中时应用特定动作的条件类。
CCIfInReg<CCAssignToReg<[SGPR0, SGPR1]>>
表示如果参数标记为在寄存器中,则分配到 SGPR0 或 SGPR1。