From: Bruno Cardoso Lopes Date: Thu, 10 Jun 2010 02:42:59 +0000 (+0000) Subject: Teach tablegen to allow "let" expressions inside multiclasses, X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=ee65db3add855bfbc4ddc7e45926d1b9bafca8a4 Teach tablegen to allow "let" expressions inside multiclasses, providing more ways to factor out commonality from the records. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@105776 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index 9d1f14e2d47..e504a894640 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -798,6 +798,32 @@ examples:

need to be added to several records, and the records do not otherwise need to be opened, as in the case with the CALL* instructions above.

+

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.

+ +
+
+multiclass basic_r<bits<4> opc> {
+  let Predicates = [HasSSE2] in {
+    def rr : Instruction<opc, "rr">;
+    def rm : Instruction<opc, "rm">;
+  }
+  let Predicates = [HasSSE3] 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/test/TableGen/LetInsideMultiClasses.td b/test/TableGen/LetInsideMultiClasses.td new file mode 100644 index 00000000000..9238bf42d9b --- /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 opc, string Name> { + bits<4> opcode = opc; + string name = Name; + bit IsDouble = 0; +} + +multiclass basic_r opc> { + let name = "newname" in { + def rr : Instruction; + def rm : Instruction; + } + + let name = "othername" in + def rx : Instruction; +} + +multiclass basic_ss opc> { + let IsDouble = 0 in + defm SS : basic_r; + + let IsDouble = 1 in + defm SD : basic_r; +} + +defm ADD : basic_ss<0xf>; + diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index f04e91a1295..49ff0b0c4cd 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 &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 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 &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 88998d40fe4..0aee931423a 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 ParseLetList(); - Record *ParseDef(MultiClass *CurMultiClass); bool ParseObjectBody(Record *CurRec); bool ParseBody(Record *CurRec); bool ParseBodyItem(Record *CurRec);