mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-13 22:24:07 +00:00
Document multiclasses and defm's
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@30030 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -30,6 +30,7 @@
|
|||||||
<li><a href="#valuedef">Value definitions</a></li>
|
<li><a href="#valuedef">Value definitions</a></li>
|
||||||
<li><a href="#recordlet">'let' expressions</a></li>
|
<li><a href="#recordlet">'let' expressions</a></li>
|
||||||
<li><a href="#templateargs">Class template arguments</a></li>
|
<li><a href="#templateargs">Class template arguments</a></li>
|
||||||
|
<li><a href="#multiclass">Multiclass definitions and instances</a></li>
|
||||||
</ol></li>
|
</ol></li>
|
||||||
<li><a href="#filescope">File scope entities</a>
|
<li><a href="#filescope">File scope entities</a>
|
||||||
<ol>
|
<ol>
|
||||||
@ -102,6 +103,10 @@ TableGen keeps track of all of the classes that are used to build up a
|
|||||||
definition, so the backend can find all definitions of a particular class, such
|
definition, so the backend can find all definitions of a particular class, such
|
||||||
as "Instruction".</p>
|
as "Instruction".</p>
|
||||||
|
|
||||||
|
<p><b>TableGen multiclasses</b> are groups of abstract records that are
|
||||||
|
instantiated all at once. Each instantiation can result in multiple TableGen
|
||||||
|
definitions.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- ======================================================================= -->
|
<!-- ======================================================================= -->
|
||||||
@ -463,16 +468,16 @@ running <tt>tblgen</tt> on the example prints the following definitions:</p>
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<b>def</b> bork { <i>// Value</i>
|
<b>def</b> bork { <i>// Value</i>
|
||||||
bit isMod = 1;
|
<b>bit</b> isMod = 1;
|
||||||
bit isRef = 0;
|
<b>bit</b> isRef = 0;
|
||||||
}
|
}
|
||||||
<b>def</b> hork { <i>// Value</i>
|
<b>def</b> hork { <i>// Value</i>
|
||||||
bit isMod = 1;
|
<b>bit</b> isMod = 1;
|
||||||
bit isRef = 1;
|
<b>bit</b> isRef = 1;
|
||||||
}
|
}
|
||||||
<b>def</b> zork { <i>// Value</i>
|
<b>def</b> zork { <i>// Value</i>
|
||||||
bit isMod = 0;
|
<b>bit</b> isMod = 0;
|
||||||
bit isRef = 1;
|
<b>bit</b> isRef = 1;
|
||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@ -483,6 +488,78 @@ X86 backend.</p>
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- -------------------------------------------------------------------------->
|
||||||
|
<div class="doc_subsubsection">
|
||||||
|
<a name="multiclass">Multiclass definitions and instances</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="doc_text">
|
||||||
|
|
||||||
|
<p>
|
||||||
|
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.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Here is an example TableGen fragment that shows this idea:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<b>def</b> ops;
|
||||||
|
<b>def</b> GPR;
|
||||||
|
<b>def</b> Imm;
|
||||||
|
<b>class</b> inst<<b>int</b> opc, <b>string</b> asmstr, <b>dag</b> operandlist>;
|
||||||
|
|
||||||
|
<b>multiclass</b> ri_inst<<b>int</b> opc, <b>string</b> 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.
|
||||||
|
<b>defm</b> ADD : ri_inst<0b111, "add">;
|
||||||
|
<b>defm</b> SUB : ri_inst<0b101, "sub">;
|
||||||
|
<b>defm</b> MUL : ri_inst<0b100, "mul">;
|
||||||
|
...
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>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:</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
<b>def</b> ops;
|
||||||
|
<b>def</b> GPR;
|
||||||
|
<b>def</b> Imm;
|
||||||
|
<b>class</b> inst<<b>int</b> opc, <b>string</b> asmstr, <b>dag</b> operandlist>;
|
||||||
|
|
||||||
|
<b>class</b> rrinst<<b>int</b> opc, <b>string</b> asmstr>
|
||||||
|
: inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
|
||||||
|
(ops GPR:$dst, GPR:$src1, GPR:$src2)>;
|
||||||
|
|
||||||
|
<b>class</b> riinst<<b>int</b> opc, <b>string</b> asmstr>
|
||||||
|
: inst<opc, !strconcat(asmstr, " $dst, $src1, $src2"),
|
||||||
|
(ops GPR:$dst, GPR:$src1, Imm:$src2)>;
|
||||||
|
|
||||||
|
// Instantiations of the ri_inst multiclass.
|
||||||
|
<b>def</b> ADD_rr : rrinst<0b111, "add">;
|
||||||
|
<b>def</b> ADD_ri : riinst<0b111, "add">;
|
||||||
|
<b>def</b> SUB_rr : rrinst<0b101, "sub">;
|
||||||
|
<b>def</b> SUB_ri : riinst<0b101, "sub">;
|
||||||
|
<b>def</b> MUL_rr : rrinst<0b100, "mul">;
|
||||||
|
<b>def</b> MUL_ri : riinst<0b100, "mul">;
|
||||||
|
...
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- ======================================================================= -->
|
<!-- ======================================================================= -->
|
||||||
<div class="doc_subsection">
|
<div class="doc_subsection">
|
||||||
<a name="filescope">File scope entities</a>
|
<a name="filescope">File scope entities</a>
|
||||||
|
Reference in New Issue
Block a user