td文件分析(1)--- X86.td

后端中的td文件内容分析,下面看X86的文件。

概述

X86.td是用于描述X86架构的目标描述文件。这个文件定义了X86处理器的特性、指令集、调度模型、寄存器信息(这些通过include引用)等基本内容,是LLVM X86后端的核心配置文件。

主要组成部分

  • 架构模式定义:定义不同位宽的工作模式
  • 处理器特性定义:包括:基础指令集特性、扩展指令集特性、系统特性、安全缓解特性、调优特性。
  • 处理器模型定义:定义不同的处理器模型/架构级别,为每个处理器指定了支持的特性和调优参数
  • 汇编语法支持:描述汇编语法,定义语法解析器和打印器

包含的其他文件:

X86.td位于X86后端描述文件的顶层,它包含并协调其他多个td文件:
X86.td (主文件)
├── X86RegisterInfo.td (寄存器定义)
├── X86RegisterBanks.td (寄存器组定义)
├── X86InstrInfo.td (指令集定义)
├── X86Schedule.td (通用调度模型)
├── X86Schedule*.td (特定处理器调度模型)
├── X86SchedPredicates.td (调度谓词)
├── X86CallingConv.td (调用约定)
└── X86PfmCounters.td (性能计数器)

X86.td包含"llvm/Target/Target.td",获取目标无关的基础定义
X86InstrInfo.td依赖于X86RegisterInfo.td中定义的寄存器
各种调度模型文件依赖于X86Schedule.td中定义的基础调度概念
处理器特定调度模型(如X86SchedSandyBridge.td)依赖于通用调度模型和指令定义

在LLVM后端中的作用

  1. 这些定义的指令信息被转成C++代码在后面的指令选择与生成过程中使用
  2. 这里的定义的处理器特性方便后面在针对不同的处理器变体生成代码时进行优化。
  3. 汇编生成和解析是必要包含的内容

详细内容

1. 定义处理的位宽模式特性

def Mode64Bit : SubtargetFeature<"64bit-mode", "In64BitMode", "true",
                                  "64-bit mode (x86_64)">;

参数:特性名称、使用的变量名、这个特性的默认值、描述
这个在后面生成代码的时候会根据特性选择,在td文件中使用In64BitMode,看是否生成对应的代码,在cpp文件中是用Mode64Bit

2. 定义处理器的ISA特性和指令集架构

def FeatureX87     : SubtargetFeature<"x87","HasX87", "true",
                                      "Enable X87 float instructions">;

参数:CPU特性名称、对应的C++变量、特性描述信息、特性以来关系
这个feature是是否启用x87浮点指令

3.Subtarget Security Mitigation features的定义

主要用于安全的,预防漏洞攻击,缓解各种CPU安全漏洞(Spectre 和 LVI),提供内存安全保护,增强控制流完整性。

  • 实现Retpoline技术来缓解Spectre v2攻击,用于控制编译器生成特定安全特性的机器码。
  • 防御Load Value Injection (LVI)攻击:禁止间接调用/分支使用内存操作数,,将RET指令分解为POP+LFENCE+JMP序列。
  • 防御针对数据加载的LVI攻击:在寄存器的间接调用/分支前插入LFENCE指令以序列化控制流。
  • 缓解推测执行攻击:在内存读取、写入和条件分支前插入推测屏障。
  • 为全局变量提供内存标记保护:使用特定的指令序列来获取全局变量地址,允许在高位地址位中使用内存标记。

4.X86 Subtarget Tuning features

描述X86的各种微架构特性,帮助编译器生成针对特定CPU优化的代码,避免使用较慢指令和特定优化。主要包含:指令性能特性(指令在某些CPU上执行较慢)、内存访问特性(标记非对齐和双内存操作)、出发运算优化(针对特定范围的数值使用更债的除法指令)、向量处理特性(描述向量指令和操作的偏好)、特殊指令优化(标记特此那个指令的依赖和优化机会)、分支优化(描述分支融合能力)。

5.X86 CPU Families

定义处理器谢列特性,Intel Atom处理器系列(也称为Bonnell微架构)

6.Register File Description

include寄存器描述文件:X86RegisterInfo.td 和 X86RegisterBanks.td。
X86RegisterInfo.td中定义所有寄存器,描述寄存器的属性和特性,定义寄存器类。
X86RegisterBanks.td中定义register bank,描述bank之间的映射关系,支持全局指令选择框架。
X86RegisterBanks是在较高层次上定义寄存器的逻辑分组,主要用于GlobalSel框架。

7.Instruction Descriptions

include指令描述文件,包含:X86Schedule.td、X86InstrInfo.td 和 X86SchedPredicates.td
def X86InstrInfo : InstrInfo定义X86InstrInfo,集成自InstrInfo。
X86InstrInfo.td 定义X86架构的所有指令,描述指令的格式、操作码和属性,定义指令的模式和匹配规则。
X86Schedule.td定义X86处理器的调度模型,描述指令的延迟、吞吐量等执行特性,定义处理器资源。
X86SchedPredicates.td 定义调度谓词,描述指令调度的条件合约束,支持基于上下文的调度决策。

8.X86 Scheduler Models

定义X86架构处理器调度模型,主要包含:指令延迟、执行端口、流水线深度、资源冲突、吞吐量等。方便重新排列指令以最大限度地利用处理器的执行资源,减少停顿,从而提高性能。
X86ScheduleAtom.td 定义最基本的处理器调度模型,包含了通用的指令调度信息,作为其他具体处理器模型的基础。
后面include的是其他的架构版本的调度模型:Intel Sandy Bridge微架构、Intel Haswell微架构、Intel Broadwell微架构、Intel Silvermont微架构、AMD Zen 1、Zen 2、Zen 3微架构、AMD Bulldozer架构、AMD Bobcat架构、Intel Skylake、Intel Ice Lake微架构。

9.X86 Processor Feature Lists

定义了不同X86处理器架构做支持的特性和调优参数。定义了从Intel Nehalem到AMD Zen3等多个处理器微架构的特性。包括MMX、SSE、AVX、AVX512等各种指令集扩展。

10.X86 processors supported.

定义 X86 架构处理器的特性、调度模型和优化参数。

11.Calling Conventions

include调用约定:CallingConv.td

12. Assembly Parser

汇编解释器,定义了两种汇编语法变体:AT&T语法和Intel语法。
AT&T语法变体(ATTAsmParserVariant):

def ATTAsmParserVariant : AsmParserVariant {
  int Variant = 0;                    // 变体标识符为0
  string Name = "att";                // 变体名称为"att"
  string CommentDelimiter = "#";      // 注释分隔符为"#"字符
  string RegisterPrefix = "%";        // 寄存器前缀为"%"
}

定义了AT&T汇编语法的解析规则
使用"#"作为注释开始标记
寄存器名需要以"%"为前缀(如%eax, %ebx)
Intel语法变体(IntelAsmParserVariant):

def IntelAsmParserVariant : AsmParserVariant {
  int Variant = 1;                    // 变体标识符为1
  string Name = "intel";             // 变体名称为"intel"
  string CommentDelimiter = ";";      // 注释分隔符为";"字符
  string RegisterPrefix = "";        // 寄存器无前缀
}

定义了Intel汇编语法的解析规则:使用";"作为注释开始标记;寄存器名不需要前缀(如eax, ebx)

13.Assembly Printers

定义了X86架构目标在LLVM中的汇编语法支持,特别是ATT和Intel两种不同的汇编语法格式。
定义汇编打印器

def ATTAsmWriter : AsmWriter {
  string AsmWriterClassName  = "ATTInstPrinter";
  int Variant = 0;
}
def IntelAsmWriter : AsmWriter {
  string AsmWriterClassName  = "IntelInstPrinter";
  int Variant = 1;
}

这部分定义了两种不同的汇编语法打印器:
ATTAsmWriter:对应AT&T语法,使用ATTInstPrinter类实现,变体编号为0
IntelAsmWriter:对应Intel语法,使用IntelInstPrinter类实现,变体编号为1
这些打印器负责将LLVM内部的机器指令表示转换为人类可读的汇编代码。AsmWriterClassName指定了实现该功能的C++类名,而Variant是一个整数标识符,用于在运行时区分不同的语法变体。
X86目标定义

def X86 : Target {
  // Information about the instructions...
  let InstructionSet = X86InstrInfo;
  let AssemblyParserVariants = [ATTAsmParserVariant, IntelAsmParserVariant];
  let AssemblyWriters = [ATTAsmWriter, IntelAsmWriter];
  let AllowRegisterRenaming = 1;
}

这部分定义了X86架构目标:
InstructionSet = X86InstrInfo:指定X86指令集信息
AssemblyParserVariants:定义支持的汇编语法解析器变体(ATT和Intel)
AssemblyWriters:定义支持的汇编语法打印器(ATT和Intel)
AllowRegisterRenaming = 1:允许寄存器重命名,这是一个优化特性
当LLVM需要将机器码转换为汇编文本时,会根据用户选择的语法(通过-x86-asm-syntax={att|intel}选项)使用相应的打印器。

AT&T和Intel语法在操作数顺序、寄存器命名等方面有显著差异:
AT&T语法:指令 源, 目标,寄存器名前缀为%
Intel语法:指令 目标, 源,寄存器名无特殊前缀

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容