From c4f614870fcf923185cd1bfd7fa915b3cc9a541e Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Sat, 5 Jun 2010 02:11:52 +0000 Subject: [PATCH] Teach tablegen to support 'defm' inside multiclasses. llvm-svn: 105519 --- llvm/docs/TableGenFundamentals.html | 44 +++++++++++++++++++ llvm/test/TableGen/DefmInsideMultiClass.td | 25 +++++++++++ llvm/utils/TableGen/TGParser.cpp | 50 ++++++++++++++++++---- llvm/utils/TableGen/TGParser.h | 2 +- 4 files changed, 111 insertions(+), 10 deletions(-) create mode 100644 llvm/test/TableGen/DefmInsideMultiClass.td diff --git a/llvm/docs/TableGenFundamentals.html b/llvm/docs/TableGenFundamentals.html index 5be11624ced3..9d1f14e2d476 100644 --- a/llvm/docs/TableGenFundamentals.html +++ b/llvm/docs/TableGenFundamentals.html @@ -687,6 +687,50 @@ Here is an example TableGen fragment that shows this idea: +

+A defm can also be used inside a multiclass providing several levels of +multiclass instanciations. +

+ +
+
+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>;
+...
+
+// Results
+def ADDPDrm { ...
+def ADDPDrr { ...
+def ADDPSrm { ...
+def ADDPSrr { ...
+def ADDSDrm { ...
+def ADDSDrr { ...
+def ADDY { ...
+def ADDX { ...
+
+
+ diff --git a/llvm/test/TableGen/DefmInsideMultiClass.td b/llvm/test/TableGen/DefmInsideMultiClass.td new file mode 100644 index 000000000000..68cc12d56811 --- /dev/null +++ b/llvm/test/TableGen/DefmInsideMultiClass.td @@ -0,0 +1,25 @@ +// RUN: tblgen %s | grep ADDPSrr | count 1 +// XFAIL: vg_leak + +class Instruction opc, string Name> { + bits<4> opcode = opc; + string name = Name; +} + +multiclass basic_r opc> { + def rr : Instruction; + def rm : Instruction; +} + +multiclass basic_s opc> { + defm SS : basic_r; + defm SD : basic_r; +} + +multiclass basic_p opc> { + defm PS : basic_r; + defm PD : basic_r; +} + +defm ADD : basic_s<0xf>, basic_p<0xf>; +defm SUB : basic_s<0xe>, basic_p<0xe>; diff --git a/llvm/utils/TableGen/TGParser.cpp b/llvm/utils/TableGen/TGParser.cpp index 8c158e0e4ee8..f04e91a1295d 100644 --- a/llvm/utils/TableGen/TGParser.cpp +++ b/llvm/utils/TableGen/TGParser.cpp @@ -1635,7 +1635,6 @@ bool TGParser::ParseObjectBody(Record *CurRec) { return ParseBody(CurRec); } - /// ParseDef - Parse and return a top level or multiclass def, return the record /// corresponding to it. This returns null on error. /// @@ -1807,8 +1806,6 @@ bool TGParser::ParseTopLevelLet() { /// MultiClassDef ::= DefInst /// bool TGParser::ParseMultiClassDef(MultiClass *CurMC) { - if (Lex.getCode() != tgtok::Def) - return TokError("expected 'def' in multiclass body"); Record *D = ParseDef(CurMC); if (D == 0) return true; @@ -1885,9 +1882,18 @@ bool TGParser::ParseMultiClass() { if (Lex.Lex() == tgtok::r_brace) // eat the '{'. return TokError("multiclass must contain at least one def"); - while (Lex.getCode() != tgtok::r_brace) - if (ParseMultiClassDef(CurMultiClass)) - return true; + 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; + } Lex.Lex(); // eat the '}'. } @@ -1900,7 +1906,7 @@ bool TGParser::ParseMultiClass() { /// /// DefMInst ::= DEFM ID ':' DefmSubClassRef ';' /// -bool TGParser::ParseDefm() { +bool TGParser::ParseDefm(MultiClass *CurMultiClass) { assert(Lex.getCode() == tgtok::Defm && "Unexpected token!"); if (Lex.Lex() != tgtok::Id) // eat the defm. return TokError("expected identifier after defm"); @@ -1991,8 +1997,34 @@ bool TGParser::ParseDefm() { return Error(DefmPrefixLoc, "def '" + CurRec->getName() + "' already defined, instantiating defm with subdef '" + DefProto->getName() + "'"); - Records.addDef(CurRec); - CurRec->resolveReferences(); + + // Don't create a top level definition for defm inside multiclasses, + // instead, only update the prototypes and bind the template args + // with the new created definition. + if (CurMultiClass) { + for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size(); + i != e; ++i) { + if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) { + Error(DefmPrefixLoc, "defm '" + CurRec->getName() + + "' already defined in this multiclass!"); + return 0; + } + } + CurMultiClass->DefPrototypes.push_back(CurRec); + + // Copy the template arguments for the multiclass into the new def. + const std::vector &TA = + CurMultiClass->Rec.getTemplateArgs(); + + for (unsigned i = 0, e = TA.size(); i != e; ++i) { + const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]); + assert(RV && "Template arg doesn't exist?"); + CurRec->addValue(*RV); + } + } else { + Records.addDef(CurRec); + CurRec->resolveReferences(); + } } if (Lex.getCode() != tgtok::comma) break; diff --git a/llvm/utils/TableGen/TGParser.h b/llvm/utils/TableGen/TGParser.h index 9f4b63460647..88998d40fe4f 100644 --- a/llvm/utils/TableGen/TGParser.h +++ b/llvm/utils/TableGen/TGParser.h @@ -74,7 +74,7 @@ private: // Parser methods. bool ParseClass(); bool ParseMultiClass(); bool ParseMultiClassDef(MultiClass *CurMC); - bool ParseDefm(); + bool ParseDefm(MultiClass *CurMultiClass = 0); bool ParseTopLevelLet(); std::vector ParseLetList();