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
This commit is contained in:
David Greene 2009-04-24 16:55:41 +00:00
parent 1c2c462d0f
commit d34a73b3b7
4 changed files with 117 additions and 30 deletions

View File

@ -1,4 +1,4 @@
// RUN: tblgen %s | grep {zing = 4} | count 4
// RUN: tblgen %s | grep {zing = 4} | count 28
class C1<int A, string B> {
int bar = A;
@ -8,25 +8,57 @@ class C1<int A, string B> {
def T : C1<4, "blah">;
multiclass t<int a> {
def S1 : C1<a, "foo"> {
multiclass t1<int a1> {
def S1 : C1<a1, "foo"> {
int foo = 4;
let bar = 1;
}
def S2 : C1<a, "bar">;
def S2 : C1<a1, "bar">;
}
multiclass s<int a, int b> : t<a> {
def S3 : C1<b, "moo"> {
multiclass t2<int a2> {
def S3 : C1<a2, "foo"> {
int foo = 4;
let bar = 1;
}
def S4 : C1<a2, "bar">;
}
multiclass s1<int as1, int bs1> : t1<as1> {
def S5 : C1<bs1, "moo"> {
int moo = 3;
let bar = 1;
}
def S4 : C1<b, "baz">;
def S6 : C1<bs1, "baz">;
}
defm FOO : s<42, 24>;
multiclass s2<int as2> : t1<as2>, t2<as2>;
multiclass s3<int as3, int bs3> : t1<as3>, t2<as3> {
def S7 : C1<bs3, "moo"> {
int moo = 3;
let bar = 1;
}
def S8 : C1<bs3, "baz">;
}
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>;

View File

@ -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) {

View File

@ -1138,7 +1138,9 @@ struct MultiClass {
Record Rec; // Placeholder for template args and Name.
typedef std::vector<Record*> RecordVector;
RecordVector DefPrototypes;
void dump() const;
MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
};

View File

@ -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<Init*> 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<Init *>::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<std::string> &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<unsigned>(),
// If a value is specified for this template arg, set it in the
// superclass now.
if (SetValue(CurRec, SubMultiClass.RefLoc, SMCTArgs[i],
std::vector<unsigned>(),
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<unsigned>(),
if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i],
std::vector<unsigned>(),
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;