http://www.llvm.org/docs/TableGen/index.html
在描述处理器结构时,需要描述很多重复的信息,如寄存器和指令集。LLVM工具链中有个TableGen工具,可以灵活地描述处理器中这些重复信息。使用TableGen工具,可以减少我们重复编写描述指令集和寄存器的代码量,在减少我们工作的同时也减少了出错的几率。所以,在LLVM中增加一种新的处理器后端时,我们通常使用TableGen工具描述新处理器后端的寄存器和指令集。
要使用TableGen工具帮助我们描述新处理器后端的指令集和寄存器,我们首先要用TableGen自定义的.td文件格式来描述,然后使用TableGen生成对应的C++代码,嵌入到LLVM中。
.td格式
TableGen文件是由一系列记录(record)组成的,记录可以分为两种:类(class)和定义(defination)。类和高级语言中的类相似用来简化对定义的书写。定义是最基本的记录形式,它使用def关键字来标记。例如def R1{string name = “R1”; }是一个定义,R1是这个定义的名字,可以是一个寄存器或者一条指令,它又一个string类型的变量name,name的值是“R1”,注意,记录中的变量都必须有值。类相对定义来讲稍微抽象一点,它的关键字是class。它是用来简化对定义中公共部分的书写。
class IntReg{bits<5> Num; }
这就是一个名为IntReg的类,bits<5>是5个比特位类型,变量名叫Num。
def R1 : IntReg { string name = " R1 " ; }
寄存器R1继承了类IntReg,R1中便有了bits<5>类型的Num,同时还有string类型的name。使用let关键字可以修改R1中继承过来的<bits>5类型的变量Num的值。例如def R2 : IntReg { let Num = 0b11111 ; },表示R2中继承过来的Num的值修改为0b11111.
TableGen支持的类型包括:
bit:1位,布尔类型
int:整形,32位的整形值
string:字符串类型,长度任意
bits<n>:位串,表示n位二进制数
list<ty>:列表,表示一个元素是tr类型的列表,tr是任意类型,包括列表本身
Class type:类,和列表类型一起使用时,用来之处列表中元素的类型为该类的子类
code:代码段类型,表示一段代码
dag:dag类型,表示嵌套有向图中一个组成元素。
.td文件中可以使用C++中的//和/**/注释符,也可以用include关键字包含另一个.td文件。使用TableGen工具的指令是:
tblgen xxx.td -gen-register-desc -o xxxGenRegisterInfo.inc //寄存器描述
tblgen xxx.td -gen-instr-desc -o xxxGenInstrInfo.inc //指令集
tblgen xxx.td -gencallingconv -o xxxGenCallingConv.inc //调用约束描述