summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDavid Greene <greened@obbligato.org>2009-04-22 16:42:54 +0000
committerDavid Greene <greened@obbligato.org>2009-04-22 16:42:54 +0000
commitde444af6bb9a8a7bb95e2a274d8fa8697e8f4e3f (patch)
tree77c944279ee1bc9f17ad62b8ad34cc567084ecfa /utils
parent20900cae35c0d18eed449a985d452a74c98ecdb2 (diff)
downloadllvm-de444af6bb9a8a7bb95e2a274d8fa8697e8f4e3f.tar.gz
llvm-de444af6bb9a8a7bb95e2a274d8fa8697e8f4e3f.tar.bz2
llvm-de444af6bb9a8a7bb95e2a274d8fa8697e8f4e3f.tar.xz
Implement multiclass inheritance.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69810 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/TGParser.cpp173
-rw-r--r--utils/TableGen/TGParser.h5
2 files changed, 175 insertions, 3 deletions
diff --git a/utils/TableGen/TGParser.cpp b/utils/TableGen/TGParser.cpp
index 32ac719966..ddaf55803f 100644
--- a/utils/TableGen/TGParser.cpp
+++ b/utils/TableGen/TGParser.cpp
@@ -25,7 +25,8 @@ using namespace llvm;
namespace llvm {
struct MultiClass {
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) {}
};
@@ -38,6 +39,15 @@ struct SubClassReference {
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
@@ -177,6 +187,85 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
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
//===----------------------------------------------------------------------===//
@@ -223,6 +312,25 @@ Record *TGParser::ParseClassID() {
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() {
if (Lex.getCode() != tgtok::Id) {
TokError("expected multiclass name");
@@ -285,6 +393,47 @@ ParseSubClassReference(Record *CurRec, bool isDefm) {
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.
/// RangePiece ::= INTVAL
/// RangePiece ::= INTVAL '-' INTVAL
@@ -1231,7 +1380,7 @@ bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
/// ParseMultiClass - Parse a multiclass definition.
///
-/// MultiClassInst ::= MULTICLASS ID TemplateArgList? '{' MultiClassDef+ '}'
+/// MultiClassInst ::= MULTICLASS ID TemplateArgList? ':' BaseMultiClassList '{' MultiClassDef+ '}'
///
bool TGParser::ParseMultiClass() {
assert(Lex.getCode() == tgtok::MultiClass && "Unexpected token");
@@ -1252,6 +1401,26 @@ bool TGParser::ParseMultiClass() {
if (ParseTemplateArgList(0))
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)
return TokError("expected '{' in multiclass definition");
diff --git a/utils/TableGen/TGParser.h b/utils/TableGen/TGParser.h
index b04139f80a..2979d0e189 100644
--- a/utils/TableGen/TGParser.h
+++ b/utils/TableGen/TGParser.h
@@ -25,6 +25,7 @@ namespace llvm {
struct Init;
struct MultiClass;
struct SubClassReference;
+ struct SubMultiClassReference;
struct LetRecord {
std::string Name;
@@ -46,7 +47,6 @@ class TGParser {
/// current value.
MultiClass *CurMultiClass;
public:
-
TGParser(TGSourceMgr &SrcMgr) : Lex(SrcMgr), CurMultiClass(0) {}
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,
const std::vector<unsigned> &BitList, Init *V);
bool AddSubClass(Record *Rec, SubClassReference &SubClass);
+ bool AddSubMultiClass(MultiClass *MV, class SubMultiClassReference &SubMultiClass);
private: // Parser methods.
bool ParseObjectList();
@@ -87,6 +88,7 @@ private: // Parser methods.
std::string ParseDeclaration(Record *CurRec, bool ParsingTemplateArgs);
SubClassReference ParseSubClassReference(Record *CurRec, bool isDefm);
+ SubMultiClassReference ParseSubMultiClassReference(MultiClass *CurMultiClass);
Init *ParseIDValue(Record *CurRec);
Init *ParseIDValue(Record *CurRec, const std::string &Name, TGLoc NameLoc);
@@ -101,6 +103,7 @@ private: // Parser methods.
RecTy *ParseType();
std::string ParseObjectName();
Record *ParseClassID();
+ MultiClass *ParseMultiClassID();
Record *ParseDefmID();
};