mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-03 01:12:53 +00:00
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:
parent
c7cafcd815
commit
5654613a01
@ -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>
|
||||
|
32
test/TableGen/DefmInherit.td
Normal file
32
test/TableGen/DefmInherit.td
Normal 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>;
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user