From 84b3598bd0ea7a1e376c36b49b52db4740a3f9af Mon Sep 17 00:00:00 2001
From: Chris Lattner
@@ -102,6 +103,10 @@
definition, so the backend can find all definitions of a particular class, such
as "Instruction".
TableGen multiclasses are groups of abstract records that are +instantiated all at once. Each instantiation can result in multiple TableGen +definitions.
+ @@ -463,16 +468,16 @@def bork { // Value - bit isMod = 1; - bit isRef = 0; + bit isMod = 1; + bit isRef = 0; } def hork { // Value - bit isMod = 1; - bit isRef = 1; + bit isMod = 1; + bit isRef = 1; } def zork { // Value - bit isMod = 0; - bit isRef = 1; + bit isMod = 0; + bit isRef = 1; }@@ -483,6 +488,78 @@ + + + +
+While classes with template arguments are a good way to factor commonality +between two instances of a definition, multiclasses allow a convenient notation +for defining multiple definitions at once (instances of implicitly constructed +classes). For example, consider an 3-address instruction set whose instructions +come in two forms: "reg = reg op reg" and "reg = reg op imm" (e.g. SPARC). In +this case, you'd like to specify in one place that this commonality exists, then +in a separate place indicate what all the ops are. +
+ ++Here is an example TableGen fragment that shows this idea: +
+ ++def ops; +def GPR; +def Imm; +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">; +defm MUL : ri_inst<0b100, "mul">; +... ++ +
The name of the resuntant definitions has the multidef fragment names + appended to them, so this defines ADD_rr, ADD_ri, SUB_rr, etc. Using a + multiclass this way is exactly equivalent to instantiating the + classes multiple times yourself, e.g. by writing:
+ ++def ops; +def GPR; +def Imm; +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">; +def MUL_rr : rrinst<0b100, "mul">; +def MUL_ri : riinst<0b100, "mul">; +... ++ +