編譯器知識雜記31——LLVM TableGen Language之multiclass和defm

TabelGen文檔:https://llvm.org/docs/TableGen/
TableGen Language文檔:TableGen Language Introduction、TableGen Language Reference

簡單記錄一下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的后面??词纠?/p>

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的用法感覺挺繞的,可以結合該工具來輔助理解和開發。

十八坰

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。