LLVM TableGen Language之multiclass和defm

文章介绍了LLVMTableGen语言中multiclass和defm的概念,用于抽象和实例化处理器的3-address指令格式。通过示例代码展示了如何使用multiclass定义不同的指令格式,以及defm如何实例化这些格式,生成具体的指令如ADD_rr、ADD_ri等。并提到了可以使用llvm-tblgen工具辅助理解和开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LLVM TableGen Language之multiclass和defm

简单记录一下multiclass和defm的语法。

假设某处理器的3-address指令有如下两种格式:

reg = reg op reg
reg = reg op imm
前2个操作数是寄存器,第3个操作数可能是寄存器,也可能是立即数。

看如下示例代码:

class inst<int opc, string asmstr, dag operandlist>;

multiclass ri_inst<int opc, string asmstr> {
  def _rr : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
                 (ops GPR:$dst, GPR:$src1, GPR:$src2)>;
  def _ri : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
                 (ops GPR:$dst, GPR:$src1, Imm:$src2)>;
}

// Instantiations of the ri_inst multiclass.
defm ADD : ri_inst<0b111, "add">;
defm SUB : ri_inst<0b101, "sub">;

multiclass ri_inst抽象了3-address指令,def _rr和def _ri分别定义上述两种指令格式。

defm实例化multiclass。以defm ADD为例,相当于定义了ADD_rr和ADD_ri两条指令(指令名字由defm后面的名字和multiclass中def后面的名字拼接组成)。

上述代码与下面的代码等价:

class inst<int opc, string asmstr, dag operandlist>;

class rrinst<int opc, string asmstr>
  : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
         (ops GPR:$dst, GPR:$src1, GPR:$src2)>;

class riinst<int opc, string asmstr>
  : inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
         (ops GPR:$dst, GPR:$src1, Imm:$src2)>;

// Instantiations of the ri_inst multiclass.
def ADD_rr : rrinst<0b111, "add">;
def ADD_ri : riinst<0b111, "add">;
def SUB_rr : rrinst<0b101, "sub">;
def SUB_ri : riinst<0b101, "sub">;

defm还可以出现在multiclass内部,看一个更复杂的例子(多层multiclass实例化):

class Instruction<bits<4> opc, string Name> {
  bits<4> opcode = opc;
  string name = Name;
}

multiclass basic_r<bits<4> opc> {
  def rr : Instruction<opc, "rr">;
  def rm : Instruction<opc, "rm">;
}

multiclass basic_s<bits<4> opc> {
  defm SS : basic_r<opc>;
  defm SD : basic_r<opc>;
  def X : Instruction<opc, "x">;
}

multiclass basic_p<bits<4> opc> {
  defm PS : basic_r<opc>;
  defm PD : basic_r<opc>;
  def Y : Instruction<opc, "y">;
}

defm ADD : basic_s<0xf>, basic_p<0xf>;

上述代码定义了ADDSSrr、ADDSSrm、ADDSDrr、ADDSDrm、ADDX、ADDPSrr、ADDPSrm、ADDPDrr、ADDPDrm、ADDY。

// Results
def ADDSSrr { ...
def ADDSSrm { ...
def ADDSDrr { ...
def ADDSDrm { ...
def ADDX { ...
def ADDPSrr { ...
def ADDPSrm { ...
def ADDPDrr { ...
def ADDPDrm { ...
def ADDY { ...

defm语句中,分号后面的类列表中即可有multiclass,也可以有class。但至少要有一个multiclass,并且class list要在最后一个multiclass的后面。看示例:

class XD { bits<4> Prefix = 11; }
class XS { bits<4> Prefix = 12; }

class I<bits<4> op> {
  bits<4> opcode = op;
}

multiclass R {
  def rr : I<4>;
  def rm : I<2>;
}

multiclass Y {
  defm SS : R, XD;
  defm SD : R, XS;
}

defm Instr : Y;

定义结果:

// Results
def InstrSSrr {
  bits<4> opcode = { 0, 1, 0, 0 }; //4
  bits<4> Prefix = { 1, 0, 1, 1 }; //11
}

def InstrSSrm {
  bits<4> opcode = { 0, 0, 1, 0 }; //2
  bits<4> Prefix = { 1, 0, 1, 1 }; //11
}

def InstrSDrr {
  bits<4> opcode = { 0, 1, 0, 0 }; //4
  bits<4> Prefix = { 1, 1, 0, 0 }; //12
}

def InstrSDrm {
  bits<4> opcode = { 0, 0, 1, 0 }; //2
  bits<4> Prefix = { 1, 1, 0, 0 }; //12
}

在最终的定义中,class中的field进行了合并。

llvm中有一个工具llvm-tblgen,可以用来查看td文件中定义的所有record。multiclass和defm的用法感觉挺绕的,可以结合该工具来辅助理解和开发。

作者:十八垧
链接:https://www.jianshu.com/p/5f55d2e9f2bf
来源:简书

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值