LLVM PC Sections Metadata¶
简介¶
PC Sections 元数据可以附加到指令和函数,对于这些指令和函数,地址,即程序计数器 (PC),将被发射到专门编码的二进制 sections 中。元数据被分配为 MD_pcsections
(!pcsections
) 类型的 MDNode
;以下章节描述了元数据格式。
元数据格式¶
可以添加任意数量交错的 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 sections 之外的优化或代码生成。
虽然依靠 LLVM IR 元数据来请求 PC sections 使上述保证相对简单,但元数据通过优化和代码生成管道的传播具有以下保证。
元数据传播¶
一般来说,LLVM 不作任何关于通过 IR 转换保留 IR 元数据(附加到 Instruction
)的保证。 当使用 PC sections 元数据时,此保证不变,并且 !pcsections
元数据在降低到机器 IR (MIR) 之前仍然是可选的。
代码生成注意事项¶
与其他 LLVM IR 元数据一样,LLVM IR 转换 pass 没有保留 !pcsections
元数据的要求,但以下情况除外
AtomicExpandPass
应根据以下规则 1-4 保留!pcsections
元数据。
当将 LLVM IR 转换为 MIR 时,!pcsections
元数据应从源 Instruction
复制到目标 MachineInstr
(使用 MachineInstr::setPCSections()
设置)。 指令选择器和 MIR 优化 pass 应按如下方式保留 PC sections 元数据
替换将保留被替换指令的 PC sections 元数据。
复制将保留被复制指令的 PC sections 元数据。
合并将保留两个指令之一的 PC sections 元数据(不保证使用哪个指令的元数据)。
删除将丢失 PC sections 元数据。
这类似于调试信息,并且 BuildMI()
助手提供了一种在 MIMetadata
捆绑包中传播调试信息和 !pcsections
元数据的便捷方法。
元数据用户注意事项¶
!pcsections
元数据的使用案例应完全容忍缺少元数据,或者插入 !pcsections
元数据的 pass 应在所有 LLVM IR 优化 pass 之后运行,以保留元数据直到转换为 MIR。