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