Allow defm to inherit from multiple multiclasses.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69832 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
David Greene 2009-04-22 22:17:51 +00:00
parent c7cafcd815
commit 5654613a01
3 changed files with 112 additions and 71 deletions

View File

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

View File

@ -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>;

View File

@ -1482,78 +1482,86 @@ bool TGParser::ParseDefm() {
TGLoc SubClassLoc = Lex.getLoc();
SubClassReference Ref = ParseSubClassReference(0, true);
if (Ref.Rec == 0) return true;
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 (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();
// 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();
}
return false;
}