LLVM PC Sections 元数据¶
简介¶
PC Sections 元数据可以附加到指令和函数上,这些指令和函数的地址,即程序计数器 (PC),需要以特殊编码的二进制段的形式输出。元数据被指定为 MDNode
的 MD_pcsections
(!pcsections
) 类型;下一节将描述元数据格式。
元数据格式¶
可以添加任意数量交错的 MDString
和常量操作数,其中新的 MDString
始终表示一个段名,后面跟着任意数量的辅助常量数据,这些数据与指令或函数的 PC 一起编码。第一个操作数必须是表示第一个段的 MDString
。
!0 = !{
!"<section#1>"
[ , !1 ... ]
[ !"<section#2">
[ , !2 ... ]
... ]
}
!1 = !{ iXX <aux-consts#1>, ... }
!2 = !{ iXX <aux-consts#2>, ... }
...
元数据中出现 section#1
、section#2
、…、section#N
会导致后端将关联指令或函数的 PC 输出到所有命名的段中。对于在段 #N 中输出的每个 PC,元组 !N
中的常量 aux-consts#N
将在 PC 后输出。可以在段名字符串后提供多个带有常量数据的元组(例如 !0 = !{"s1", !1, !2}
),并且单个常量元组可以重复用于不同的段(例如 !0 = !{"s1", !1, "s2", !1}
)。
二进制编码¶
指令会导致输出单个 PC,而函数会导致输出函数的起始地址和一个 32 位大小。后面跟着在 MD_pcsections
元数据中跟随相应段名的辅助常量。
为了避免最终二进制文件中的重定位,存储在 entry
处的每个 PC 地址都是相对重定位,计算方式为 pc - entry
。要解码,用户必须计算 entry + *entry
。
每个条目的大小取决于代码模型。在大型和中等大小的代码模型中,条目大小与指针大小匹配。对于任何较小的代码模型,条目大小仅为 32 位。
编码选项¶
可以在第一个 MDString
操作数中传递可选的编码选项:<section>!<options>
。以下选项可用
C
– 将大小为 2-8 字节的常量整数压缩为 ULEB128;这包括函数大小(但不包括 PC 条目)。
例如,foo!C
将输出到段 foo
中,所有常量都编码为 ULEB128。
代码生成保证¶
将 !pcsections
元数据附加到 LLVM IR 指令不应该影响请求的 PC 段之外的优化或代码生成。
虽然依赖 LLVM IR 元数据来请求 PC 段使上述保证相对简单,但元数据在优化和代码生成管道中的传播具有以下保证。
元数据传播¶
通常,LLVM不保证通过 IR 转换保留 IR 元数据(附加到 Instruction
)。使用 PC Sections 元数据时,此保证保持不变,并且 !pcsections
元数据在降低到机器 IR (MIR) 之前仍然是可选的。
代码生成说明¶
与其他 LLVM IR 元数据一样,LLVM IR 转换过程没有要求保留 !pcsections
元数据,但以下情况除外
AtomicExpandPass
应根据以下规则 1-4 保留!pcsections
元数据。
将 LLVM IR 转换为 MIR 时,应将 !pcsections
元数据从源 Instruction
复制到目标 MachineInstr
(使用 MachineInstr::setPCSections()
设置)。指令选择器和 MIR 优化过程应按如下方式保留 PC Sections 元数据
替换将保留被替换指令的 PC Sections 元数据。
复制将保留被复制指令的 PC Sections 元数据。
合并将保留两个指令之一的 PC Sections 元数据(不保证使用哪个指令的元数据)。
删除将丢失 PC Sections 元数据。
这类似于调试信息,并且 BuildMI()
帮助程序提供了一种方便的方法来在 MIMetadata
捆绑包中传播调试信息和 !pcsections
元数据。
元数据用户说明¶
!pcsections
元数据的用例应该完全容忍缺少元数据,或者插入 !pcsections
元数据的过程应该在所有 LLVM IR 优化过程之后运行,以保留元数据直到被转换为 MIR。