From d34a73b3b709001c56db68a4d9a84e5d2002b1f0 Mon Sep 17 00:00:00 2001 From: David Greene Date: Fri, 24 Apr 2009 16:55:41 +0000 Subject: [PATCH] Fix multiclass inheritance to limit value resolution to new defs added by base multiclasses. Do not attempt to alter defs from previous base multiclasses. This fixes multiple multiclass inheritance. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69974 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/TableGen/MultiClassInherit.td | 50 +++++++++++++++---- utils/TableGen/Record.cpp | 14 ++++++ utils/TableGen/Record.h | 4 +- utils/TableGen/TGParser.cpp | 79 ++++++++++++++++++++++-------- 4 files changed, 117 insertions(+), 30 deletions(-) diff --git a/test/TableGen/MultiClassInherit.td b/test/TableGen/MultiClassInherit.td index 5a1fc7ee405..d4c4ce58daa 100644 --- a/test/TableGen/MultiClassInherit.td +++ b/test/TableGen/MultiClassInherit.td @@ -1,4 +1,4 @@ -// RUN: tblgen %s | grep {zing = 4} | count 4 +// RUN: tblgen %s | grep {zing = 4} | count 28 class C1 { int bar = A; @@ -8,25 +8,57 @@ class C1 { def T : C1<4, "blah">; -multiclass t { - def S1 : C1 { +multiclass t1 { + def S1 : C1 { int foo = 4; let bar = 1; } - def S2 : C1; + def S2 : C1; } -multiclass s : t { - def S3 : C1 { +multiclass t2 { + def S3 : C1 { + int foo = 4; + let bar = 1; + } + def S4 : C1; +} + +multiclass s1 : t1 { + def S5 : C1 { int moo = 3; let bar = 1; } - def S4 : C1; + def S6 : C1; } -defm FOO : s<42, 24>; +multiclass s2 : t1, t2; + +multiclass s3 : t1, t2 { + def S7 : C1 { + int moo = 3; + let bar = 1; + } + def S8 : C1; +} + +let zing = 4 in +defm FOO1 : s1<42, 24>; + +let zing = 4 in +defm FOO2 : s2<99>; + +let zing = 4 in +defm FOO3 : s3<84, 48>; def T4 : C1<6, "foo">; let zing = 4 in - defm BAZ : s<3, 4>; + defm BAZ1 : s1<3, 4>; + +let zing = 4 in + defm BAZ2 : s2<5>; + +let zing = 4 in + defm BAZ3 : s3<6, 7>; + diff --git a/utils/TableGen/Record.cpp b/utils/TableGen/Record.cpp index 9ce645de34f..2e64c838ab7 100644 --- a/utils/TableGen/Record.cpp +++ b/utils/TableGen/Record.cpp @@ -1060,6 +1060,20 @@ std::string Record::getValueAsCode(const std::string &FieldName) const { } +void MultiClass::dump() const { + cerr << "Record:\n"; + Rec.dump(); + + cerr << "Defs:\n"; + for (RecordVector::const_iterator r = DefPrototypes.begin(), + rend = DefPrototypes.end(); + r != rend; + ++r) { + (*r)->dump(); + } +} + + void RecordKeeper::dump() const { cerr << *this; } std::ostream &llvm::operator<<(std::ostream &OS, const RecordKeeper &RK) { diff --git a/utils/TableGen/Record.h b/utils/TableGen/Record.h index 4aec3320a2a..615ecebecf8 100644 --- a/utils/TableGen/Record.h +++ b/utils/TableGen/Record.h @@ -1138,7 +1138,9 @@ struct MultiClass { Record Rec; // Placeholder for template args and Name. typedef std::vector RecordVector; RecordVector DefPrototypes; - + + void dump() const; + MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {} }; diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp index c3b17ac6039..8d0c9e5002f 100644 --- a/utils/TableGen/TGParser.cpp +++ b/utils/TableGen/TGParser.cpp @@ -16,6 +16,7 @@ #include "TGParser.h" #include "Record.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Streams.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -28,7 +29,7 @@ struct SubClassReference { Record *Rec; std::vector TemplateArgs; SubClassReference() : Rec(0) {} - + bool isInvalid() const { return Rec == 0; } }; @@ -39,8 +40,23 @@ struct SubMultiClassReference { SubMultiClassReference() : MC(0) {} bool isInvalid() const { return MC == 0; } + void dump() const; }; - + +void SubMultiClassReference::dump() const { + cerr << "Multiclass:\n"; + + MC->dump(); + + cerr << "Template args:\n"; + for (std::vector::const_iterator i = TemplateArgs.begin(), + iend = TemplateArgs.end(); + i != iend; + ++i) { + (*i)->dump(); + } +} + } // end namespace llvm bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) { @@ -182,7 +198,8 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) { /// AddSubMultiClass - Add SubMultiClass as a subclass to /// CurMultiClass, resolving its template args as SubMultiClass's /// template arguments. -bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassReference &SubMultiClass) { +bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, + class SubMultiClassReference &SubMultiClass) { MultiClass *SMC = SubMultiClass.MC; Record *CurRec = &CurMultiClass->Rec; @@ -194,6 +211,8 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassRe if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i])) return true; + int newDefStart = CurMultiClass->DefPrototypes.size(); + // Add all of the defs in the subclass into the current multiclass. for (MultiClass::RecordVector::const_iterator i = SMC->DefPrototypes.begin(), iend = SMC->DefPrototypes.end(); @@ -212,16 +231,20 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassRe const std::vector &SMCTArgs = SMC->Rec.getTemplateArgs(); - // Ensure that an appropriate number of template arguments are specified. + // Ensure that an appropriate number of template arguments are + // specified. if (SMCTArgs.size() < SubMultiClass.TemplateArgs.size()) - return Error(SubMultiClass.RefLoc, "More template args specified than expected"); + return Error(SubMultiClass.RefLoc, + "More template args specified than expected"); // 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 = SMCTArgs.size(); i != e; ++i) { if (i < SubMultiClass.TemplateArgs.size()) { - // If a value is specified for this template arg, set it in the superclass now. - if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], std::vector(), + // If a value is specified for this template arg, set it in the + // superclass now. + if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -231,14 +254,17 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassRe // Now remove it. CurRec->removeValue(SMCTArgs[i]); - // If a value is specified for this template arg, set it in the defs now. - for (MultiClass::RecordVector::iterator j = CurMultiClass->DefPrototypes.begin(), + // If a value is specified for this template arg, set it in the + // new defs now. + for (MultiClass::RecordVector::iterator j = + CurMultiClass->DefPrototypes.begin() + newDefStart, jend = CurMultiClass->DefPrototypes.end(); j != jend; ++j) { Record *Def = *j; - if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], std::vector(), + if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], + std::vector(), SubMultiClass.TemplateArgs[i])) return true; @@ -249,7 +275,8 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMultiClass, class SubMultiClassRe Def->removeValue(SMCTArgs[i]); } } else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) { - return Error(SubMultiClass.RefLoc,"Value not specified for template argument #" + return Error(SubMultiClass.RefLoc, + "Value not specified for template argument #" + utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" + SMC->Rec.getName() + "'!"); } @@ -1490,8 +1517,12 @@ bool TGParser::ParseMultiClass() { if (ParseTemplateArgList(0)) return true; + bool inherits = false; + // If there are submulticlasses, parse them. if (Lex.getCode() == tgtok::colon) { + inherits = true; + Lex.Lex(); // Read all of the submulticlasses. @@ -1510,17 +1541,25 @@ bool TGParser::ParseMultiClass() { } } - if (Lex.getCode() != tgtok::l_brace) - return TokError("expected '{' in multiclass definition"); - - if (Lex.Lex() == tgtok::r_brace) // eat the '{'. - return TokError("multiclass must contain at least one def"); + if (Lex.getCode() != tgtok::l_brace) { + if (!inherits) + return TokError("expected '{' in multiclass definition"); + else + if (Lex.getCode() != tgtok::semi) + return TokError("expected ';' in multiclass definition"); + else + Lex.Lex(); // eat the ';'. + } + else { + 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 (ParseMultiClassDef(CurMultiClass)) + return true; - Lex.Lex(); // eat the '}'. + Lex.Lex(); // eat the '}'. + } CurMultiClass = 0; return false; -- 2.34.1