diff options
author | David Greene <greened@obbligato.org> | 2009-04-22 22:17:51 +0000 |
---|---|---|
committer | David Greene <greened@obbligato.org> | 2009-04-22 22:17:51 +0000 |
commit | 5654613a013b94a92f9ed65e1a2f34e0a8d9cfdf (patch) | |
tree | d29f21688078d41bdb26dc0a2ae1503978ccebe5 | |
parent | c7cafcd815519b06318629b424abe746437e1389 (diff) |
Allow defm to inherit from multiple multiclasses.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69832 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | docs/TableGenFundamentals.html | 7 | ||||
-rw-r--r-- | test/TableGen/DefmInherit.td | 32 | ||||
-rw-r--r-- | utils/TableGen/TGParser.cpp | 144 |
3 files changed, 112 insertions, 71 deletions
diff --git a/docs/TableGenFundamentals.html b/docs/TableGenFundamentals.html index 42839176cb..c9d1fa3b3f 100644 --- a/docs/TableGenFundamentals.html +++ b/docs/TableGenFundamentals.html @@ -632,9 +632,10 @@ Here is an example TableGen fragment that shows this idea: <p>The name of the resultant definitions has the multidef fragment names appended to them, so this defines <tt>ADD_rr</tt>, <tt>ADD_ri</tt>, - <tt>SUB_rr</tt>, etc. Using a multiclass this way is exactly - equivalent to instantiating the classes multiple times yourself, - e.g. by writing:</p> + <tt>SUB_rr</tt>, etc. A defm may inherit from multiple multiclasses, + instantiating definitions from each multiclass. Using a multiclass + this way is exactly equivalent to instantiating the classes multiple + times yourself, e.g. by writing:</p> <div class="doc_code"> <pre> diff --git a/test/TableGen/DefmInherit.td b/test/TableGen/DefmInherit.td new file mode 100644 index 0000000000..4f37edf056 --- /dev/null +++ b/test/TableGen/DefmInherit.td @@ -0,0 +1,32 @@ +// RUN: tblgen %s | grep {zing = 4} | count 4 + +class C1<int A, string B> { + int bar = A; + string thestr = B; + int zing; +} + +def T : C1<4, "blah">; + +multiclass t<int a> { + def S1 : C1<a, "foo"> { + int foo = 4; + let bar = 1; + } + def S2 : C1<a, "bar">; +} + +multiclass s<int a> { + def S3 : C1<a, "moo"> { + int moo = 3; + let bar = 1; + } + def S4 : C1<a, "baz">; +} + +defm FOO : t<42>, s<24>; + +def T4 : C1<6, "foo">; + +let zing = 4 in + defm BAZ : t<3>, s<4>; diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index 45ad5792f9..d7feb98d2a 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -1482,77 +1482,85 @@ bool TGParser::ParseDefm() { TGLoc SubClassLoc = Lex.getLoc(); SubClassReference Ref = ParseSubClassReference(0, true); - if (Ref.Rec == 0) return true; - - if (Lex.getCode() != tgtok::semi) - return TokError("expected ';' at end of defm"); - Lex.Lex(); - - // To instantiate a multiclass, we need to first get the multiclass, then - // instantiate each def contained in the multiclass with the SubClassRef - // template parameters. - MultiClass *MC = MultiClasses[Ref.Rec->getName()]; - assert(MC && "Didn't lookup multiclass correctly?"); - std::vector<Init*> &TemplateVals = Ref.TemplateArgs; - - // Verify that the correct number of template arguments were specified. - const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs(); - if (TArgs.size() < TemplateVals.size()) - return Error(SubClassLoc, - "more template args specified than multiclass expects"); - - // Loop over all the def's in the multiclass, instantiating each one. - for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { - Record *DefProto = MC->DefPrototypes[i]; - - // Add the suffix to the defm name to get the new name. - Record *CurRec = new Record(DefmPrefix + DefProto->getName(),DefmPrefixLoc); - - SubClassReference Ref; - Ref.RefLoc = DefmPrefixLoc; - Ref.Rec = DefProto; - AddSubClass(CurRec, Ref); - - // Loop over all of the template arguments, setting them to the specified - // value or leaving them as the default if necessary. - for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { - if (i < TemplateVals.size()) { // A value is specified for this temp-arg? - // Set it now. - if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(), - TemplateVals[i])) - return true; - - // Resolve it next. - CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); - - // Now remove it. - CurRec->removeValue(TArgs[i]); - - } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { - return Error(SubClassLoc, "value not specified for template argument #"+ - utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + - MC->Rec.getName() + "'"); + + while (1) { + if (Ref.Rec == 0) return true; + + // To instantiate a multiclass, we need to first get the multiclass, then + // instantiate each def contained in the multiclass with the SubClassRef + // template parameters. + MultiClass *MC = MultiClasses[Ref.Rec->getName()]; + assert(MC && "Didn't lookup multiclass correctly?"); + std::vector<Init*> &TemplateVals = Ref.TemplateArgs; + + // Verify that the correct number of template arguments were specified. + const std::vector<std::string> &TArgs = MC->Rec.getTemplateArgs(); + if (TArgs.size() < TemplateVals.size()) + return Error(SubClassLoc, + "more template args specified than multiclass expects"); + + // Loop over all the def's in the multiclass, instantiating each one. + for (unsigned i = 0, e = MC->DefPrototypes.size(); i != e; ++i) { + Record *DefProto = MC->DefPrototypes[i]; + + // Add the suffix to the defm name to get the new name. + Record *CurRec = new Record(DefmPrefix + DefProto->getName(), DefmPrefixLoc); + + SubClassReference Ref; + Ref.RefLoc = DefmPrefixLoc; + Ref.Rec = DefProto; + AddSubClass(CurRec, Ref); + + // Loop over all of the template arguments, setting them to the specified + // value or leaving them as the default if necessary. + for (unsigned i = 0, e = TArgs.size(); i != e; ++i) { + if (i < TemplateVals.size()) { // A value is specified for this temp-arg? + // Set it now. + if (SetValue(CurRec, DefmPrefixLoc, TArgs[i], std::vector<unsigned>(), + TemplateVals[i])) + return true; + + // Resolve it next. + CurRec->resolveReferencesTo(CurRec->getValue(TArgs[i])); + + // Now remove it. + CurRec->removeValue(TArgs[i]); + + } else if (!CurRec->getValue(TArgs[i])->getValue()->isComplete()) { + return Error(SubClassLoc, "value not specified for template argument #"+ + utostr(i) + " (" + TArgs[i] + ") of multiclassclass '" + + MC->Rec.getName() + "'"); + } } + + // If the mdef is inside a 'let' expression, add to each def. + for (unsigned i = 0, e = LetStack.size(); i != e; ++i) + for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) + if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, + LetStack[i][j].Bits, LetStack[i][j].Value)) { + Error(DefmPrefixLoc, "when instantiating this defm"); + return true; + } + + // Ensure redefinition doesn't happen. + if (Records.getDef(CurRec->getName())) + return Error(DefmPrefixLoc, "def '" + CurRec->getName() + + "' already defined, instantiating defm with subdef '" + + DefProto->getName() + "'"); + Records.addDef(CurRec); + CurRec->resolveReferences(); } - - // If the mdef is inside a 'let' expression, add to each def. - for (unsigned i = 0, e = LetStack.size(); i != e; ++i) - for (unsigned j = 0, e = LetStack[i].size(); j != e; ++j) - if (SetValue(CurRec, LetStack[i][j].Loc, LetStack[i][j].Name, - LetStack[i][j].Bits, LetStack[i][j].Value)) { - Error(DefmPrefixLoc, "when instantiating this defm"); - return true; - } - - - // Ensure redefinition doesn't happen. - if (Records.getDef(CurRec->getName())) - return Error(DefmPrefixLoc, "def '" + CurRec->getName() + - "' already defined, instantiating defm with subdef '" + - DefProto->getName() + "'"); - Records.addDef(CurRec); - CurRec->resolveReferences(); + + if (Lex.getCode() != tgtok::comma) break; + Lex.Lex(); // eat ','. + + SubClassLoc = Lex.getLoc(); + Ref = ParseSubClassReference(0, true); } + + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' at end of defm"); + Lex.Lex(); return false; } |