summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen/TGParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils/TableGen/TGParser.cpp')
-rw-r--r--contrib/llvm/utils/TableGen/TGParser.cpp165
1 files changed, 119 insertions, 46 deletions
diff --git a/contrib/llvm/utils/TableGen/TGParser.cpp b/contrib/llvm/utils/TableGen/TGParser.cpp
index 8c158e0..f81aabe 100644
--- a/contrib/llvm/utils/TableGen/TGParser.cpp
+++ b/contrib/llvm/utils/TableGen/TGParser.cpp
@@ -1635,13 +1635,12 @@ bool TGParser::ParseObjectBody(Record *CurRec) {
return ParseBody(CurRec);
}
-
/// ParseDef - Parse and return a top level or multiclass def, return the record
/// corresponding to it. This returns null on error.
///
/// DefInst ::= DEF ObjectName ObjectBody
///
-llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
+bool TGParser::ParseDef(MultiClass *CurMultiClass) {
SMLoc DefLoc = Lex.getLoc();
assert(Lex.getCode() == tgtok::Def && "Unknown tok");
Lex.Lex(); // Eat the 'def' token.
@@ -1655,7 +1654,7 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
// Ensure redefinition doesn't happen.
if (Records.getDef(CurRec->getName())) {
Error(DefLoc, "def '" + CurRec->getName() + "' already defined");
- return 0;
+ return true;
}
Records.addDef(CurRec);
} else {
@@ -1664,20 +1663,33 @@ llvm::Record *TGParser::ParseDef(MultiClass *CurMultiClass) {
if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
Error(DefLoc, "def '" + CurRec->getName() +
"' already defined in this multiclass!");
- return 0;
+ return true;
}
CurMultiClass->DefPrototypes.push_back(CurRec);
}
if (ParseObjectBody(CurRec))
- return 0;
+ return true;
if (CurMultiClass == 0) // Def's in multiclasses aren't really defs.
CurRec->resolveReferences();
// If ObjectBody has template arguments, it's an error.
assert(CurRec->getTemplateArgs().empty() && "How'd this get template args?");
- return CurRec;
+
+ if (CurMultiClass) {
+ // Copy the template arguments for the multiclass into the def.
+ const std::vector<std::string> &TArgs =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TArgs[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ }
+
+ return false;
}
@@ -1758,12 +1770,12 @@ std::vector<LetRecord> TGParser::ParseLetList() {
}
/// ParseTopLevelLet - Parse a 'let' at top level. This can be a couple of
-/// different related productions.
+/// different related productions. This works inside multiclasses too.
///
/// Object ::= LET LetList IN '{' ObjectList '}'
/// Object ::= LET LetList IN Object
///
-bool TGParser::ParseTopLevelLet() {
+bool TGParser::ParseTopLevelLet(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Let && "Unexpected token");
Lex.Lex();
@@ -1779,7 +1791,7 @@ bool TGParser::ParseTopLevelLet() {
// If this is a scalar let, just handle it now
if (Lex.getCode() != tgtok::l_brace) {
// LET LetList IN Object
- if (ParseObject())
+ if (ParseObject(CurMultiClass))
return true;
} else { // Object ::= LETCommand '{' ObjectList '}'
SMLoc BraceLoc = Lex.getLoc();
@@ -1787,7 +1799,7 @@ bool TGParser::ParseTopLevelLet() {
Lex.Lex(); // eat the '{'.
// Parse the object list.
- if (ParseObjectList())
+ if (ParseObjectList(CurMultiClass))
return true;
if (Lex.getCode() != tgtok::r_brace) {
@@ -1802,29 +1814,6 @@ bool TGParser::ParseTopLevelLet() {
return false;
}
-/// ParseMultiClassDef - Parse a def in a multiclass context.
-///
-/// MultiClassDef ::= DefInst
-///
-bool TGParser::ParseMultiClassDef(MultiClass *CurMC) {
- if (Lex.getCode() != tgtok::Def)
- return TokError("expected 'def' in multiclass body");
-
- Record *D = ParseDef(CurMC);
- if (D == 0) return true;
-
- // Copy the template arguments for the multiclass into the def.
- const std::vector<std::string> &TArgs = CurMC->Rec.getTemplateArgs();
-
- for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
- const RecordVal *RV = CurMC->Rec.getValue(TArgs[i]);
- assert(RV && "Template arg doesn't exist?");
- D->addValue(*RV);
- }
-
- return false;
-}
-
/// ParseMultiClass - Parse a multiclass definition.
///
/// MultiClassInst ::= MULTICLASS ID TemplateArgList?
@@ -1885,10 +1874,18 @@ bool TGParser::ParseMultiClass() {
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) {
+ switch (Lex.getCode()) {
+ default:
+ return TokError("expected 'let', 'def' or 'defm' in multiclass body");
+ case tgtok::Let:
+ case tgtok::Def:
+ case tgtok::Defm:
+ if (ParseObject(CurMultiClass))
+ return true;
+ break;
+ }
+ }
Lex.Lex(); // eat the '}'.
}
@@ -1900,7 +1897,7 @@ bool TGParser::ParseMultiClass() {
///
/// DefMInst ::= DEFM ID ':' DefmSubClassRef ';'
///
-bool TGParser::ParseDefm() {
+bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
assert(Lex.getCode() == tgtok::Defm && "Unexpected token!");
if (Lex.Lex() != tgtok::Id) // eat the defm.
return TokError("expected identifier after defm");
@@ -1910,6 +1907,12 @@ bool TGParser::ParseDefm() {
if (Lex.Lex() != tgtok::colon)
return TokError("expected ':' after defm identifier");
+ // Keep track of the new generated record definitions.
+ std::vector<Record*> NewRecDefs;
+
+ // This record also inherits from a regular class (non-multiclass)?
+ bool InheritFromClass = false;
+
// eat the colon.
Lex.Lex();
@@ -1991,17 +1994,87 @@ bool TGParser::ParseDefm() {
return Error(DefmPrefixLoc, "def '" + CurRec->getName() +
"' already defined, instantiating defm with subdef '" +
DefProto->getName() + "'");
- Records.addDef(CurRec);
- CurRec->resolveReferences();
+
+ // Don't create a top level definition for defm inside multiclasses,
+ // instead, only update the prototypes and bind the template args
+ // with the new created definition.
+ if (CurMultiClass) {
+ for (unsigned i = 0, e = CurMultiClass->DefPrototypes.size();
+ i != e; ++i) {
+ if (CurMultiClass->DefPrototypes[i]->getName() == CurRec->getName()) {
+ Error(DefmPrefixLoc, "defm '" + CurRec->getName() +
+ "' already defined in this multiclass!");
+ return 0;
+ }
+ }
+ CurMultiClass->DefPrototypes.push_back(CurRec);
+
+ // Copy the template arguments for the multiclass into the new def.
+ const std::vector<std::string> &TA =
+ CurMultiClass->Rec.getTemplateArgs();
+
+ for (unsigned i = 0, e = TA.size(); i != e; ++i) {
+ const RecordVal *RV = CurMultiClass->Rec.getValue(TA[i]);
+ assert(RV && "Template arg doesn't exist?");
+ CurRec->addValue(*RV);
+ }
+ } else {
+ Records.addDef(CurRec);
+ }
+
+ NewRecDefs.push_back(CurRec);
}
if (Lex.getCode() != tgtok::comma) break;
Lex.Lex(); // eat ','.
SubClassLoc = Lex.getLoc();
+
+ // A defm can inherit from regular classes (non-multiclass) as
+ // long as they come in the end of the inheritance list.
+ InheritFromClass = (Records.getClass(Lex.getCurStrVal()) != 0);
+
+ if (InheritFromClass)
+ break;
+
Ref = ParseSubClassReference(0, true);
}
+ if (InheritFromClass) {
+ // Process all the classes to inherit as if they were part of a
+ // regular 'def' and inherit all record values.
+ SubClassReference SubClass = ParseSubClassReference(0, false);
+ while (1) {
+ // Check for error.
+ if (SubClass.Rec == 0) return true;
+
+ // Get the expanded definition prototypes and teach them about
+ // the record values the current class to inherit has
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i) {
+ Record *CurRec = NewRecDefs[i];
+
+ // Add it.
+ if (AddSubClass(CurRec, SubClass))
+ return true;
+
+ // Process any variables on the let stack.
+ 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))
+ return true;
+ }
+
+ if (Lex.getCode() != tgtok::comma) break;
+ Lex.Lex(); // eat ','.
+ SubClass = ParseSubClassReference(0, false);
+ }
+ }
+
+ if (!CurMultiClass)
+ for (unsigned i = 0, e = NewRecDefs.size(); i != e; ++i)
+ NewRecDefs[i]->resolveReferences();
+
if (Lex.getCode() != tgtok::semi)
return TokError("expected ';' at end of defm");
Lex.Lex();
@@ -2016,12 +2089,12 @@ bool TGParser::ParseDefm() {
/// Object ::= DefMInst
/// Object ::= LETCommand '{' ObjectList '}'
/// Object ::= LETCommand Object
-bool TGParser::ParseObject() {
+bool TGParser::ParseObject(MultiClass *MC) {
switch (Lex.getCode()) {
default: assert(0 && "This is not an object");
- case tgtok::Let: return ParseTopLevelLet();
- case tgtok::Def: return ParseDef(0) == 0;
- case tgtok::Defm: return ParseDefm();
+ case tgtok::Let: return ParseTopLevelLet(MC);
+ case tgtok::Def: return ParseDef(MC);
+ case tgtok::Defm: return ParseDefm(MC);
case tgtok::Class: return ParseClass();
case tgtok::MultiClass: return ParseMultiClass();
}
@@ -2029,9 +2102,9 @@ bool TGParser::ParseObject() {
/// ParseObjectList
/// ObjectList :== Object*
-bool TGParser::ParseObjectList() {
+bool TGParser::ParseObjectList(MultiClass *MC) {
while (isObjectStart(Lex.getCode())) {
- if (ParseObject())
+ if (ParseObject(MC))
return true;
}
return false;
OpenPOWER on IntegriCloud