summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/TableGenFundamentals.html26
-rw-r--r--test/TableGen/LetInsideMultiClasses.td29
-rw-r--r--utils/TableGen/TGParser.cpp85
-rw-r--r--utils/TableGen/TGParser.h11
4 files changed, 98 insertions, 53 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html
index 9d1f14e2d4..e504a89464 100644
--- a/docs/TableGenFundamentals.html
+++ b/docs/TableGenFundamentals.html
@@ -798,6 +798,32 @@ examples:</p>
need to be added to several records, and the records do not otherwise need to be
opened, as in the case with the <tt>CALL*</tt> instructions above.</p>
+<p>It's also possible to use "let" expressions inside multiclasses, providing
+more ways to factor out commonality from the records, specially if using
+several levels of multiclass instanciations. This also avoids the need of using
+"let" expressions within subsequent records inside a multiclass.</p>
+
+<div class="doc_code">
+<pre>
+<b>multiclass </b>basic_r&lt;bits&lt;4&gt; opc&gt; {
+ <b>let </b>Predicates = [HasSSE2] in {
+ <b>def </b>rr : Instruction&lt;opc, "rr"&gt;;
+ <b>def </b>rm : Instruction&lt;opc, "rm"&gt;;
+ }
+ <b>let </b>Predicates = [HasSSE3] in
+ <b>def </b>rx : Instruction&lt;opc, "rx"&gt;;
+}
+
+<b>multiclass </b>basic_ss&lt;bits&lt;4&gt; opc&gt; {
+ <b>let </b>IsDouble = 0 in
+ <b>defm </b>SS : basic_r&lt;opc&gt;;
+
+ <b>let </b>IsDouble = 1 in
+ <b>defm </b>SD : basic_r&lt;opc&gt;;
+}
+
+<b>defm </b>ADD : basic_ss&lt;0xf&gt;;
+</pre>
</div>
<!-- *********************************************************************** -->
diff --git a/test/TableGen/LetInsideMultiClasses.td b/test/TableGen/LetInsideMultiClasses.td
new file mode 100644
index 0000000000..9238bf42d9
--- /dev/null
+++ b/test/TableGen/LetInsideMultiClasses.td
@@ -0,0 +1,29 @@
+// RUN: tblgen %s | grep "bit IsDouble = 1;" | count 3
+// XFAIL: vg_leak
+
+class Instruction<bits<4> opc, string Name> {
+ bits<4> opcode = opc;
+ string name = Name;
+ bit IsDouble = 0;
+}
+
+multiclass basic_r<bits<4> opc> {
+ let name = "newname" in {
+ def rr : Instruction<opc, "rr">;
+ def rm : Instruction<opc, "rm">;
+ }
+
+ let name = "othername" in
+ def rx : Instruction<opc, "rx">;
+}
+
+multiclass basic_ss<bits<4> opc> {
+ let IsDouble = 0 in
+ defm SS : basic_r<opc>;
+
+ let IsDouble = 1 in
+ defm SD : basic_r<opc>;
+}
+
+defm ADD : basic_ss<0xf>;
+
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index f04e91a129..49ff0b0c4c 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -1640,7 +1640,7 @@ bool TGParser::ParseObjectBody(Record *CurRec) {
///
/// DefInst ::= DEF ObjectName ObjectBody
///
-llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
+bool TGParser::ParseDef(MultiClass *CurMultiClass) {
SMLoc DefLoc = Lex.getLoc();
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
Lex.Lex(); // Eat the 'def' token.
@@ -1654,7 +1654,7 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
// Ensure redefinition doesn't happen.
if (Records.getDef(CurRec->getName())) {
Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
- return 0;
+ return true;
}
Records.addDef(CurRec);
} else {
@@ -1663,20 +1663,33 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
Error(DefLoc, "def '" + CurRec->getName() +
"' already defined in this multiclass!");
- return 0;
+ return true;
}
CurMultiClass->DefPrototypes.push_back(CurRec);
}
if (ParseObjectBody(CurRec))
- return 0;
+ return true;
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
CurRec->resolveReferences();
// If ObjectBody has template arguments, it's an error.
assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
- return CurRec;
+
+ if (CurMultiClass) {
+ // Copy the template arguments for the multiclass into the def.
+ const std::vector<std::string> &TArgs =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ }
+
+ return false;
}
@@ -1757,12 +1770,12 @@ std::vector<LetRecord> TGParser::ParseLetList() {
}
/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
-/// different related productions.
+/// different related productions. This works inside multiclasses too.
///
/// Object ::= LET LetList IN '{' ObjectList '}'
/// Object ::= LET LetList IN Object
///
-bool TGParser::ParseTopLevelLet() {
+bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
Lex.Lex();
@@ -1778,7 +1791,7 @@ bool TGParser::ParseTopLevelLet() {
// If this is a scalar let, just handle it now
if (Lex.getCode() != tgtok::l_brace) {
// LET LetList IN Object
- if (ParseObject())
+ if (ParseObject(CurMultiClass))
return true;
} else { // Object ::= LETCommand '{' ObjectList '}'
SMLoc BraceLoc = Lex.getLoc();
@@ -1786,7 +1799,7 @@ bool TGParser::ParseTopLevelLet() {
Lex.Lex(); // eat the '{'.
// Parse the object list.
- if (ParseObjectList())
+ if (ParseObjectList(CurMultiClass))
return true;
if (Lex.getCode() != tgtok::r_brace) {
@@ -1801,27 +1814,6 @@ bool TGParser::ParseTopLevelLet() {
return false;
}
-/// ParseMultiClassDef - Parse a def in a multiclass context.
-///
-/// MultiClassDef ::= DefInst
-///
-bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
-
- Record *D = ParseDef(CurMC);
- if (D == 0) return true;
-
- // Copy the template arguments for the multiclass into the def.
- const std::vector<std::string> &TArgs = CurMC->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]);
- assert(RV && "Template arg doesn't exist?");
- D->addValue(*RV);
- }
-
- return false;
-}
-
/// ParseMultiClass - Parse a multiclass definition.
///
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
@@ -1883,18 +1875,17 @@ bool TGParser::ParseMultiClass() {
return TokError("multiclass must contain at least one def");
while (Lex.getCode() != tgtok::r_brace) {
- if (Lex.getCode() != tgtok::Defm && Lex.getCode() != tgtok::Def)
- return TokError("expected 'def' or 'defm' in multiclass body");
-
- if (Lex.getCode() == tgtok::Def)
- if (ParseMultiClassDef(CurMultiClass))
- return true;
-
- if (Lex.getCode() == tgtok::Defm)
- if (ParseDefm(CurMultiClass))
- return true;
+ switch (Lex.getCode()) {
+ default:
+ return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+ case tgtok::Let:
+ case tgtok::Def:
+ case tgtok::Defm:
+ if (ParseObject(CurMultiClass))
+ return true;
+ break;
+ }
}
-
Lex.Lex(); // eat the '}'.
}
@@ -2048,12 +2039,12 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
/// Object ::= DefMInst
/// Object ::= LETCommand '{' ObjectList '}'
/// Object ::= LETCommand Object
-bool TGParser::ParseObject() {
+bool TGParser::ParseObject(MultiClass *MC) {
switch (Lex.getCode()) {
default: assert(0 && "This is not an object");
- case tgtok::Let: return ParseTopLevelLet();
- case tgtok::Def: return ParseDef(0) == 0;
- case tgtok::Defm: return ParseDefm();
+ case tgtok::Let: return ParseTopLevelLet(MC);
+ case tgtok::Def: return ParseDef(MC);
+ case tgtok::Defm: return ParseDefm(MC);
case tgtok::Class: return ParseClass();
case tgtok::MultiClass: return ParseMultiClass();
}
@@ -2061,9 +2052,9 @@ bool TGParser::ParseObject() {
/// ParseObjectList
/// ObjectList :== Object*
-bool TGParser::ParseObjectList() {
+bool TGParser::ParseObjectList(MultiClass *MC) {
while (isObjectStart(Lex.getCode())) {
- if (ParseObject())
+ if (ParseObject(MC))
return true;
}
return false;
diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h
index 88998d40fe..0aee931423 100644
--- a/utils/TableGen/TGParser.h
+++ b/utils/TableGen/TGParser.h
@@ -69,16 +69,15 @@ private: // Semantic analysis methods.
SubMultiClassReference &SubMultiClass);
private: // Parser methods.
- bool ParseObjectList();
- bool ParseObject();
+ bool ParseObjectList(MultiClass *MC = 0);
+ bool ParseObject(MultiClass *MC);
bool ParseClass();
bool ParseMultiClass();
- bool ParseMultiClassDef(MultiClass *CurMC);
- bool ParseDefm(MultiClass *CurMultiClass = 0);
- bool ParseTopLevelLet();
+ bool ParseDefm(MultiClass *CurMultiClass);
+ bool ParseDef(MultiClass *CurMultiClass);
+ bool ParseTopLevelLet(MultiClass *CurMultiClass);
std::vector<LetRecord> ParseLetList();
- Record *ParseDef(MultiClass *CurMultiClass);
bool ParseObjectBody(Record *CurRec);
bool ParseBody(Record *CurRec);
bool ParseBodyItem(Record *CurRec);