CallingConv.td文件解析

CallingConv.td文件的作用是什么

定义调用约定(Calling Convention)的文件,主要作用包括:
寄存器保存规则定义
明确规定了在不同调用约定下,哪些寄存器是被调用者必须保存的
这对于函数调用时的寄存器使用和保存至关重要
支持多种调用约定
支持纯整数、单精度浮点、双精度浮点等多种调用约定
为不同场景提供合适的寄存器保存策略
中断处理支持
为中断处理程序定义了特殊的寄存器保存规则
确保中断处理程序能够正确保存和恢复所有可能使用的寄存器
编译器后端支持
这些定义被 LLVM 后端用来生成正确的函数调用代码
影响寄存器分配、函数序言(prologue)和尾声(epilogue)的生成

CallingConv.td文件的构成是什么

  1. 基本调用约定定义
    调用约定实际上是在 RISCVISelLowering.cpp 中通过 CC_RISCV 函数以自定义代码实现的。这个 td 文件主要定义了被调用者保存寄存器(Callee Saved Registers)的规则。
  2. 被调用者保存寄存器定义
    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 调用约定
  1. 特殊场景定义
    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。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容