mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-10-11 23:25:15 +00:00
Implement multiclass inheritance.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69810 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
20900cae35
commit
de444af6bb
@ -104,8 +104,10 @@ definition, so the backend can find all definitions of a particular class, such
|
|||||||
as "Instruction".</p>
|
as "Instruction".</p>
|
||||||
|
|
||||||
<p><b>TableGen multiclasses</b> are groups of abstract records that are
|
<p><b>TableGen multiclasses</b> are groups of abstract records that are
|
||||||
instantiated all at once. Each instantiation can result in multiple TableGen
|
instantiated all at once. Each instantiation can result in multiple
|
||||||
definitions.</p>
|
TableGen definitions. If a multiclass inherits from another multiclass,
|
||||||
|
the definitions in the sub-multiclass become part of the current
|
||||||
|
multiclass, as if they were declared in the current multiclass.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
32
test/TableGen/MultiClassInherit.td
Normal file
32
test/TableGen/MultiClassInherit.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, int b> : t<a> {
|
||||||
|
def S3 : C1<b, "moo"> {
|
||||||
|
int moo = 3;
|
||||||
|
let bar = 1;
|
||||||
|
}
|
||||||
|
def S4 : C1<b, "baz">;
|
||||||
|
}
|
||||||
|
|
||||||
|
defm FOO : s<42, 24>;
|
||||||
|
|
||||||
|
def T4 : C1<6, "foo">;
|
||||||
|
|
||||||
|
let zing = 4 in
|
||||||
|
defm BAZ : s<3, 4>;
|
@ -25,7 +25,8 @@ using namespace llvm;
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
struct MultiClass {
|
struct MultiClass {
|
||||||
Record Rec; // Placeholder for template args and Name.
|
Record Rec; // Placeholder for template args and Name.
|
||||||
std::vector<Record*> DefPrototypes;
|
typedef std::vector<Record*> RecordVector;
|
||||||
|
RecordVector DefPrototypes;
|
||||||
|
|
||||||
MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
|
MultiClass(const std::string &Name, TGLoc Loc) : Rec(Name, Loc) {}
|
||||||
};
|
};
|
||||||
@ -39,6 +40,15 @@ struct SubClassReference {
|
|||||||
bool isInvalid() const { return Rec == 0; }
|
bool isInvalid() const { return Rec == 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SubMultiClassReference {
|
||||||
|
TGLoc RefLoc;
|
||||||
|
MultiClass *MC;
|
||||||
|
std::vector<Init*> TemplateArgs;
|
||||||
|
SubMultiClassReference() : MC(0) {}
|
||||||
|
|
||||||
|
bool isInvalid() const { return MC == 0; }
|
||||||
|
};
|
||||||
|
|
||||||
} // end namespace llvm
|
} // end namespace llvm
|
||||||
|
|
||||||
bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) {
|
bool TGParser::AddValue(Record *CurRec, TGLoc Loc, const RecordVal &RV) {
|
||||||
@ -177,6 +187,85 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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) {
|
||||||
|
MultiClass *SMC = SubMultiClass.MC;
|
||||||
|
Record *CurRec = &CurMultiClass->Rec;
|
||||||
|
|
||||||
|
const std::vector<RecordVal> &MCVals = CurMultiClass->Rec.getValues();
|
||||||
|
|
||||||
|
// Add all of the values in the subclass into the current class.
|
||||||
|
const std::vector<RecordVal> &SMCVals = SMC->Rec.getValues();
|
||||||
|
for (unsigned i = 0, e = SMCVals.size(); i != e; ++i)
|
||||||
|
if (AddValue(CurRec, SubMultiClass.RefLoc, SMCVals[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// 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();
|
||||||
|
i != iend;
|
||||||
|
++i) {
|
||||||
|
// Clone the def and add it to the current multiclass
|
||||||
|
Record *NewDef = new Record(**i);
|
||||||
|
|
||||||
|
// Add all of the values in the superclass into the current def.
|
||||||
|
for (unsigned i = 0, e = MCVals.size(); i != e; ++i)
|
||||||
|
if (AddValue(NewDef, SubMultiClass.RefLoc, MCVals[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
CurMultiClass->DefPrototypes.push_back(NewDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::string> &SMCTArgs = SMC->Rec.getTemplateArgs();
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
// 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>(),
|
||||||
|
SubMultiClass.TemplateArgs[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Resolve it next.
|
||||||
|
CurRec->resolveReferencesTo(CurRec->getValue(SMCTArgs[i]));
|
||||||
|
|
||||||
|
// 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(),
|
||||||
|
jend = CurMultiClass->DefPrototypes.end();
|
||||||
|
j != jend;
|
||||||
|
++j) {
|
||||||
|
Record *Def = *j;
|
||||||
|
|
||||||
|
if (SetValue(Def, SubMultiClass.RefLoc, SMCTArgs[i], std::vector<unsigned>(),
|
||||||
|
SubMultiClass.TemplateArgs[i]))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Resolve it next.
|
||||||
|
Def->resolveReferencesTo(Def->getValue(SMCTArgs[i]));
|
||||||
|
|
||||||
|
// Now remove it
|
||||||
|
Def->removeValue(SMCTArgs[i]);
|
||||||
|
}
|
||||||
|
} else if (!CurRec->getValue(SMCTArgs[i])->getValue()->isComplete()) {
|
||||||
|
return Error(SubMultiClass.RefLoc,"Value not specified for template argument #"
|
||||||
|
+ utostr(i) + " (" + SMCTArgs[i] + ") of subclass '" +
|
||||||
|
SMC->Rec.getName() + "'!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Parser Code
|
// Parser Code
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -223,6 +312,25 @@ Record *TGParser::ParseClassID() {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ParseMultiClassID - Parse and resolve a reference to a multiclass name. This returns
|
||||||
|
/// null on error.
|
||||||
|
///
|
||||||
|
/// MultiClassID ::= ID
|
||||||
|
///
|
||||||
|
MultiClass *TGParser::ParseMultiClassID() {
|
||||||
|
if (Lex.getCode() != tgtok::Id) {
|
||||||
|
TokError("expected name for ClassID");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiClass *Result = MultiClasses[Lex.getCurStrVal()];
|
||||||
|
if (Result == 0)
|
||||||
|
TokError("Couldn't find class '" + Lex.getCurStrVal() + "'");
|
||||||
|
|
||||||
|
Lex.Lex();
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
Record *TGParser::ParseDefmID() {
|
Record *TGParser::ParseDefmID() {
|
||||||
if (Lex.getCode() != tgtok::Id) {
|
if (Lex.getCode() != tgtok::Id) {
|
||||||
TokError("expected multiclass name");
|
TokError("expected multiclass name");
|
||||||
@ -285,6 +393,47 @@ ParseSubClassReference(Record *CurRec, bool isDefm) {
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ParseSubMultiClassReference - Parse a reference to a subclass or to a templated
|
||||||
|
/// submulticlass. This returns a SubMultiClassRefTy with a null Record* on error.
|
||||||
|
///
|
||||||
|
/// SubMultiClassRef ::= MultiClassID
|
||||||
|
/// SubMultiClassRef ::= MultiClassID '<' ValueList '>'
|
||||||
|
///
|
||||||
|
SubMultiClassReference TGParser::
|
||||||
|
ParseSubMultiClassReference(MultiClass *CurMC) {
|
||||||
|
SubMultiClassReference Result;
|
||||||
|
Result.RefLoc = Lex.getLoc();
|
||||||
|
|
||||||
|
Result.MC = ParseMultiClassID();
|
||||||
|
if (Result.MC == 0) return Result;
|
||||||
|
|
||||||
|
// If there is no template arg list, we're done.
|
||||||
|
if (Lex.getCode() != tgtok::less)
|
||||||
|
return Result;
|
||||||
|
Lex.Lex(); // Eat the '<'
|
||||||
|
|
||||||
|
if (Lex.getCode() == tgtok::greater) {
|
||||||
|
TokError("subclass reference requires a non-empty list of template values");
|
||||||
|
Result.MC = 0;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result.TemplateArgs = ParseValueList(&CurMC->Rec);
|
||||||
|
if (Result.TemplateArgs.empty()) {
|
||||||
|
Result.MC = 0; // Error parsing value list.
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Lex.getCode() != tgtok::greater) {
|
||||||
|
TokError("expected '>' in template value list");
|
||||||
|
Result.MC = 0;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
Lex.Lex();
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/// ParseRangePiece - Parse a bit/value range.
|
/// ParseRangePiece - Parse a bit/value range.
|
||||||
/// RangePiece ::= INTVAL
|
/// RangePiece ::= INTVAL
|
||||||
/// RangePiece ::= INTVAL '-' INTVAL
|
/// RangePiece ::= INTVAL '-' INTVAL
|
||||||
@ -1231,7 +1380,7 @@ bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
|
|||||||
|
|
||||||
/// ParseMultiClass - Parse a multiclass definition.
|
/// ParseMultiClass - Parse a multiclass definition.
|
||||||
///
|
///
|
||||||
/// MultiClassInst ::= MULTICLASS ID TemplateArgList? '{' MultiClassDef+ '}'
|
/// MultiClassInst ::= MULTICLASS ID TemplateArgList? ':' BaseMultiClassList '{' MultiClassDef+ '}'
|
||||||
///
|
///
|
||||||
bool TGParser::ParseMultiClass() {
|
bool TGParser::ParseMultiClass() {
|
||||||
assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
|
assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
|
||||||
@ -1252,6 +1401,26 @@ bool TGParser::ParseMultiClass() {
|
|||||||
if (ParseTemplateArgList(0))
|
if (ParseTemplateArgList(0))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// If there are submulticlasses, parse them.
|
||||||
|
if (Lex.getCode() == tgtok::colon) {
|
||||||
|
Lex.Lex();
|
||||||
|
|
||||||
|
// Read all of the submulticlasses.
|
||||||
|
SubMultiClassReference SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
|
||||||
|
while (1) {
|
||||||
|
// Check for error.
|
||||||
|
if (SubMultiClass.MC == 0) return true;
|
||||||
|
|
||||||
|
// Add it.
|
||||||
|
if (AddSubMultiClass(CurMultiClass, SubMultiClass))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (Lex.getCode() != tgtok::comma) break;
|
||||||
|
Lex.Lex(); // eat ','.
|
||||||
|
SubMultiClass = ParseSubMultiClassReference(CurMultiClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Lex.getCode() != tgtok::l_brace)
|
if (Lex.getCode() != tgtok::l_brace)
|
||||||
return TokError("expected '{' in multiclass definition");
|
return TokError("expected '{' in multiclass definition");
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ namespace llvm {
|
|||||||
struct Init;
|
struct Init;
|
||||||
struct MultiClass;
|
struct MultiClass;
|
||||||
struct SubClassReference;
|
struct SubClassReference;
|
||||||
|
struct SubMultiClassReference;
|
||||||
|
|
||||||
struct LetRecord {
|
struct LetRecord {
|
||||||
std::string Name;
|
std::string Name;
|
||||||
@ -46,7 +47,6 @@ class TGParser {
|
|||||||
/// current value.
|
/// current value.
|
||||||
MultiClass *CurMultiClass;
|
MultiClass *CurMultiClass;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TGParser(TGSourceMgr &SrcMgr) : Lex(SrcMgr), CurMultiClass(0) {}
|
TGParser(TGSourceMgr &SrcMgr) : Lex(SrcMgr), CurMultiClass(0) {}
|
||||||
|
|
||||||
void setIncludeDirs(const std::vector<std::string> &D){Lex.setIncludeDirs(D);}
|
void setIncludeDirs(const std::vector<std::string> &D){Lex.setIncludeDirs(D);}
|
||||||
@ -67,6 +67,7 @@ private: // Semantic analysis methods.
|
|||||||
bool SetValue(Record *TheRec, TGLoc Loc, const std::string &ValName,
|
bool SetValue(Record *TheRec, TGLoc Loc, const std::string &ValName,
|
||||||
const std::vector<unsigned> &BitList, Init *V);
|
const std::vector<unsigned> &BitList, Init *V);
|
||||||
bool AddSubClass(Record *Rec, SubClassReference &SubClass);
|
bool AddSubClass(Record *Rec, SubClassReference &SubClass);
|
||||||
|
bool AddSubMultiClass(MultiClass *MV, class SubMultiClassReference &SubMultiClass);
|
||||||
|
|
||||||
private: // Parser methods.
|
private: // Parser methods.
|
||||||
bool ParseObjectList();
|
bool ParseObjectList();
|
||||||
@ -87,6 +88,7 @@ private: // Parser methods.
|
|||||||
std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
|
std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
|
||||||
|
|
||||||
SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
|
SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
|
||||||
|
SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMultiClass);
|
||||||
|
|
||||||
Init *ParseIDValue(Record *CurRec);
|
Init *ParseIDValue(Record *CurRec);
|
||||||
Init *ParseIDValue(Record *CurRec, const std::string &Name, TGLoc NameLoc);
|
Init *ParseIDValue(Record *CurRec, const std::string &Name, TGLoc NameLoc);
|
||||||
@ -101,6 +103,7 @@ private: // Parser methods.
|
|||||||
RecTy *ParseType();
|
RecTy *ParseType();
|
||||||
std::string ParseObjectName();
|
std::string ParseObjectName();
|
||||||
Record *ParseClassID();
|
Record *ParseClassID();
|
||||||
|
MultiClass *ParseMultiClassID();
|
||||||
Record *ParseDefmID();
|
Record *ParseDefmID();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user