LLVM中描述ISA指令的接口位置及相关定义方式咨询
LLVM ISA指令定义与自动生成指引
核心文件位置
- 架构专属TableGen定义文件:所有ISA指令、寄存器、寻址模式的元定义都集中在
llvm-project/llvm/lib/Target/[你的架构名]/目录下,核心文件包括:[Arch]InstrInfo.td:指令集的核心定义,包含每条指令的操作码、操作数、汇编格式、二进制编码规则[Arch]RegisterInfo.td:寄存器类划分、寄存器别名、寄存器分配规则定义[Arch]CallingConv.td:调用约定相关规则定义
这些文件会依赖LLVM顶层的基础TableGen模板,比如llvm/include/llvm/Target/Target.td(定义了Instruction、RegisterClass等核心基类)。
- 自动生成的代码文件:TableGen工具处理上述.td文件后,会在构建目录的
llvm-project/build/lib/Target/[Arch]/下生成.inc后缀的代码片段,比如[Arch]GenInstrInfo.inc、[Arch]GenRegisterInfo.inc。这些片段会被手动编写的[Arch]InstrInfo.cpp、[Arch]RegisterInfo.cpp包含,成为LLVM目标架构接口的具体实现。
TableGen与LLVM接口的关联
TableGen是LLVM的元编程工具,核心作用是用声明式的元数据描述ISA细节,自动生成重复的C++代码,和LLVM接口的关联逻辑如下:
- 元数据描述:你在.td文件中基于LLVM预定义的模板(比如
Instruction基类),填充ISA指令的属性——比如操作码值、操作数类型(寄存器/立即数/内存)、汇编输出格式、二进制编码位布局。 - 代码生成:LLVM自带的TableGen后端(比如
InstrInfoEmitter)会解析这些.td定义,生成包含指令枚举、指令描述结构体、操作数验证逻辑的C++代码片段(.inc文件)。 - 接口对接:手动编写的
[Arch]InstrInfo.cpp会继承LLVM的TargetInstrInfo抽象类,通过包含生成的.inc文件,把TableGen生成的指令信息注入到LLVM的代码生成流水线中——比如实现getInstrDescriptor()方法,让编译器的指令选择、调度阶段能访问到你的ISA指令定义。
实现ISA全指令自动生成的建议
- 先从示例入手:找LLVM自带的简单架构(比如SPIRV、Mips)的.td文件,逐行对比.td定义和生成的.inc文件内容,用
llvm-tblgen工具手动执行转换:
直观理解TableGen如何把元描述转换成可执行的C++代码。llvm-tblgen -gen-instr-info llvm/lib/Target/SystemZ/SystemZInstrInfo.td -o SystemZGenInstrInfo.inc - 用TableGen批量生成指令:如果你的ISA有大量同构指令(比如算术运算、逻辑运算只是操作码和操作数类型不同),用TableGen的
foreach循环批量生成,避免手动重复编写。比如:foreach OpCode = [ADD, SUB, MUL, DIV] in { def !concat(OpCode, "RegReg") : MyArchInstFormat<0b001, (outs GPR:$dst), (ins GPR:$src1, GPR:$src2), !strconcat(OpCode, " $dst, $src1, $src2")>; } - 复用LLVM的预定义组件:不要从零实现指令格式,基于LLVM提供的
Instruction、Operand、RegisterClass等模板扩展,这样生成的代码能直接对接LLVM的代码生成接口,减少自定义逻辑的工作量。 - 优先看内部文档:LLVM源码中的
llvm/docs/TableGen/目录下有官方指引,TableGenIntro.rst讲基础语法,TargetDesc.rst专门讲如何用TableGen定义目标架构,内容比外部资源更准确。
内容的提问来源于stack exchange,提问作者Kevin Stefanov
相关产品推荐
相关产品推荐

