summaryrefslogtreecommitdiffstats
path: root/llvm/lib/TableGen/TGParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/TableGen/TGParser.cpp')
-rw-r--r--llvm/lib/TableGen/TGParser.cpp316
1 files changed, 209 insertions, 107 deletions
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index a0ec4dbfdc7..1d1f3603c83 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -110,6 +110,24 @@ static void checkConcrete(Record &R) {
}
}
+/// Return an Init with a qualifier prefix referring
+/// to CurRec's name.
+static Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
+ Init *Name, StringRef Scoper) {
+ Init *NewName =
+ BinOpInit::getStrConcat(CurRec.getNameInit(), StringInit::get(Scoper));
+ NewName = BinOpInit::getStrConcat(NewName, Name);
+ if (CurMultiClass && Scoper != "::") {
+ Init *Prefix = BinOpInit::getStrConcat(CurMultiClass->Rec.getNameInit(),
+ StringInit::get("::"));
+ NewName = BinOpInit::getStrConcat(Prefix, NewName);
+ }
+
+ if (BinOpInit *BinOp = dyn_cast<BinOpInit>(NewName))
+ NewName = BinOp->Fold(&CurRec);
+ return NewName;
+}
+
/// Return the qualified version of the implicit 'NAME' template argument.
static Init *QualifiedNameOfImplicitName(Record &Rec,
MultiClass *MC = nullptr) {
@@ -271,6 +289,18 @@ bool TGParser::AddSubClass(Record *CurRec, SubClassReference &SubClass) {
return false;
}
+bool TGParser::AddSubClass(RecordsEntry &Entry, SubClassReference &SubClass) {
+ if (Entry.Rec)
+ return AddSubClass(Entry.Rec.get(), SubClass);
+
+ for (auto &E : Entry.Loop->Entries) {
+ if (AddSubClass(E, SubClass))
+ return true;
+ }
+
+ return false;
+}
+
/// AddSubMultiClass - Add SubMultiClass as a subclass to
/// CurMC, resolving its template args as SubMultiClass's
/// template arguments.
@@ -285,7 +315,7 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
// Prepare the mapping of template argument name to value, filling in default
// values if necessary.
- SmallVector<std::pair<Init *, Init *>, 8> TemplateArgs;
+ SubstStack TemplateArgs;
for (unsigned i = 0, e = SMCTArgs.size(); i != e; ++i) {
if (i < SubMultiClass.TemplateArgs.size()) {
TemplateArgs.emplace_back(SMCTArgs[i], SubMultiClass.TemplateArgs[i]);
@@ -307,85 +337,105 @@ bool TGParser::AddSubMultiClass(MultiClass *CurMC,
VarInit::get(QualifiedNameOfImplicitName(CurMC), StringRecTy::get()));
// Add all of the defs in the subclass into the current multiclass.
- for (const std::unique_ptr<Record> &Rec : SMC->DefPrototypes) {
- auto NewDef = make_unique<Record>(*Rec);
+ return resolve(SMC->Entries, TemplateArgs, false, &CurMC->Entries);
+}
- MapResolver R(NewDef.get());
- for (const auto &TArg : TemplateArgs)
- R.set(TArg.first, TArg.second);
- NewDef->resolveReferences(R);
+/// Add a record or foreach loop to the current context (global record keeper,
+/// current inner-most foreach loop, or multiclass).
+bool TGParser::addEntry(RecordsEntry E) {
+ assert(!E.Rec || !E.Loop);
- CurMC->DefPrototypes.push_back(std::move(NewDef));
+ if (!Loops.empty()) {
+ Loops.back()->Entries.push_back(std::move(E));
+ return false;
}
- return false;
-}
-
-/// Add a record that results from 'def' or 'defm', after template arguments
-/// and the external let stack have been resolved.
-///
-/// Apply foreach loops, resolve internal variable references, and add to the
-/// current multi class or the global record keeper as appropriate.
-bool TGParser::addDef(std::unique_ptr<Record> Rec) {
- IterSet IterVals;
+ if (E.Loop) {
+ SubstStack Stack;
+ return resolve(*E.Loop, Stack, CurMultiClass == nullptr,
+ CurMultiClass ? &CurMultiClass->Entries : nullptr);
+ }
- if (Loops.empty())
- return addDefOne(std::move(Rec), IterVals);
+ if (CurMultiClass) {
+ CurMultiClass->Entries.push_back(std::move(E));
+ return false;
+ }
- return addDefForeach(Rec.get(), IterVals);
+ return addDefOne(std::move(E.Rec));
}
-/// Recursive helper function for addDef/addDefOne to resolve references to
-/// foreach variables.
-bool TGParser::addDefForeach(Record *Rec, IterSet &IterVals) {
- if (IterVals.size() != Loops.size()) {
- assert(IterVals.size() < Loops.size());
- ForeachLoop &CurLoop = Loops[IterVals.size()];
- ListInit *List = CurLoop.ListValue;
-
- // Process each value.
- for (unsigned i = 0; i < List->size(); ++i) {
- IterVals.push_back(IterRecord(CurLoop.IterVar, List->getElement(i)));
- if (addDefForeach(Rec, IterVals))
- return true;
- IterVals.pop_back();
- }
- return false;
+/// Resolve the entries in \p Loop, going over inner loops recursively
+/// and making the given subsitutions of (name, value) pairs.
+///
+/// The resulting records are stored in \p Dest if non-null. Otherwise, they
+/// are added to the global record keeper.
+bool TGParser::resolve(const ForeachLoop &Loop, SubstStack &Substs,
+ bool Final, std::vector<RecordsEntry> *Dest,
+ SMLoc *Loc) {
+ MapResolver R;
+ for (const auto &S : Substs)
+ R.set(S.first, S.second);
+ Init *List = Loop.ListValue->resolveReferences(R);
+ auto LI = dyn_cast<ListInit>(List);
+ if (!LI) {
+ if (!Final) {
+ Dest->emplace_back(make_unique<ForeachLoop>(Loop.Loc, Loop.IterVar,
+ List));
+ return resolve(Loop.Entries, Substs, Final, &Dest->back().Loop->Entries,
+ Loc);
+ }
+
+ PrintError(Loop.Loc, Twine("attempting to loop over '") +
+ List->getAsString() + "', expected a list");
+ return true;
}
- // This is the bottom of the recursion. We have all of the iterator values
- // for this point in the iteration space. Instantiate a new record to
- // reflect this combination of values.
- auto IterRec = make_unique<Record>(*Rec);
- return addDefOne(std::move(IterRec), IterVals);
+ bool Error = false;
+ for (auto Elt : *LI) {
+ Substs.emplace_back(Loop.IterVar->getNameInit(), Elt);
+ Error = resolve(Loop.Entries, Substs, Final, Dest);
+ Substs.pop_back();
+ if (Error)
+ break;
+ }
+ return Error;
}
-/// After resolving foreach loops, add the record as a prototype to the
-/// current multiclass, or resolve fully and add to the record keeper.
-bool TGParser::addDefOne(std::unique_ptr<Record> Rec, IterSet &IterVals) {
- MapResolver R(Rec.get());
-
- for (IterRecord &IR : IterVals)
- R.set(IR.IterVar->getNameInit(), IR.IterValue);
+/// Resolve the entries in \p Source, going over loops recursively and
+/// making the given substitutions of (name, value) pairs.
+///
+/// The resulting records are stored in \p Dest if non-null. Otherwise, they
+/// are added to the global record keeper.
+bool TGParser::resolve(const std::vector<RecordsEntry> &Source,
+ SubstStack &Substs, bool Final,
+ std::vector<RecordsEntry> *Dest, SMLoc *Loc) {
+ bool Error = false;
+ for (auto &E : Source) {
+ if (E.Loop) {
+ Error = resolve(*E.Loop, Substs, Final, Dest);
+ } else {
+ auto Rec = make_unique<Record>(*E.Rec);
+ if (Loc)
+ Rec->appendLoc(*Loc);
- Rec->resolveReferences(R);
+ MapResolver R(Rec.get());
+ for (const auto &S : Substs)
+ R.set(S.first, S.second);
+ Rec->resolveReferences(R);
- if (CurMultiClass) {
- if (!Rec->isAnonymous()) {
- for (const auto &Proto : CurMultiClass->DefPrototypes) {
- if (Proto->getNameInit() == Rec->getNameInit()) {
- PrintError(Rec->getLoc(),
- Twine("def '") + Rec->getNameInitAsString() +
- "' already defined in this multiclass!");
- PrintNote(Proto->getLoc(), "location of previous definition");
- return true;
- }
- }
+ if (Dest)
+ Dest->push_back(std::move(Rec));
+ else
+ Error = addDefOne(std::move(Rec));
}
- CurMultiClass->DefPrototypes.emplace_back(std::move(Rec));
- return false;
+ if (Error)
+ break;
}
+ return Error;
+}
+/// Resolve the record fully and add it to the record keeper.
+bool TGParser::addDefOne(std::unique_ptr<Record> Rec) {
if (Record *Prev = Records.getDef(Rec->getNameInitAsString())) {
if (!Rec->isAnonymous()) {
PrintError(Rec->getLoc(),
@@ -804,7 +854,7 @@ Init *TGParser::ParseIDValue(Record *CurRec, StringInit *Name, SMLoc NameLoc,
// If this is in a foreach loop, make sure it's not a loop iterator
for (const auto &L : Loops) {
- VarInit *IterVar = dyn_cast<VarInit>(L.IterVar);
+ VarInit *IterVar = dyn_cast<VarInit>(L->IterVar);
if (IterVar && IterVar->getNameInit() == Name)
return IterVar;
}
@@ -1158,7 +1208,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
Init *LHS = StringInit::get(Lex.getCurStrVal());
- if (CurRec->getValue(LHS)) {
+ if (CurRec && CurRec->getValue(LHS)) {
TokError((Twine("iteration variable '") + LHS->getAsString() +
"' already defined")
.str());
@@ -1217,9 +1267,18 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
return nullptr;
}
- CurRec->addValue(RecordVal(LHS, InEltType, false));
- Init *RHS = ParseValue(CurRec, OutEltType);
- CurRec->removeValue(LHS);
+ // We need to create a temporary record to provide a scope for the iteration
+ // variable while parsing top-level foreach's.
+ std::unique_ptr<Record> ParseRecTmp;
+ Record *ParseRec = CurRec;
+ if (!ParseRec) {
+ ParseRecTmp = make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);
+ ParseRec = ParseRecTmp.get();
+ }
+
+ ParseRec->addValue(RecordVal(LHS, InEltType, false));
+ Init *RHS = ParseValue(ParseRec, OutEltType);
+ ParseRec->removeValue(LHS);
if (!RHS)
return nullptr;
@@ -1441,7 +1500,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
}
Init *A = StringInit::get(Lex.getCurStrVal());
- if (CurRec->getValue(A)) {
+ if (CurRec && CurRec->getValue(A)) {
TokError((Twine("left !foldl variable '") + A->getAsString() +
"' already defined")
.str());
@@ -1459,7 +1518,7 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
}
Init *B = StringInit::get(Lex.getCurStrVal());
- if (CurRec->getValue(B)) {
+ if (CurRec && CurRec->getValue(B)) {
TokError((Twine("right !foldl variable '") + B->getAsString() +
"' already defined")
.str());
@@ -1472,11 +1531,20 @@ Init *TGParser::ParseOperation(Record *CurRec, RecTy *ItemType) {
}
Lex.Lex(); // eat the ','
- CurRec->addValue(RecordVal(A, Start->getType(), false));
- CurRec->addValue(RecordVal(B, ListType->getElementType(), false));
- Init *ExprUntyped = ParseValue(CurRec);
- CurRec->removeValue(A);
- CurRec->removeValue(B);
+ // We need to create a temporary record to provide a scope for the iteration
+ // variable while parsing top-level foreach's.
+ std::unique_ptr<Record> ParseRecTmp;
+ Record *ParseRec = CurRec;
+ if (!ParseRec) {
+ ParseRecTmp = make_unique<Record>(".parse", ArrayRef<SMLoc>{}, Records);
+ ParseRec = ParseRecTmp.get();
+ }
+
+ ParseRec->addValue(RecordVal(A, Start->getType(), false));
+ ParseRec->addValue(RecordVal(B, ListType->getElementType(), false));
+ Init *ExprUntyped = ParseValue(ParseRec);
+ ParseRec->removeValue(A);
+ ParseRec->removeValue(B);
if (!ExprUntyped)
return nullptr;
@@ -2191,7 +2259,7 @@ Init *TGParser::ParseDeclaration(Record *CurRec,
/// ForeachDeclaration ::= ID '=' RangePiece
/// ForeachDeclaration ::= ID '=' Value
///
-VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
+VarInit *TGParser::ParseForeachDeclaration(Init *&ForeachListValue) {
if (Lex.getCode() != tgtok::Id) {
TokError("Expected identifier in foreach declaration");
return nullptr;
@@ -2231,9 +2299,10 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
default: {
SMLoc ValueLoc = Lex.getLoc();
Init *I = ParseValue(nullptr);
- if (!isa<ListInit>(I)) {
+ TypedInit *TI = dyn_cast<TypedInit>(I);
+ if (!TI || !isa<ListRecTy>(TI->getType())) {
std::string Type;
- if (TypedInit *TI = dyn_cast<TypedInit>(I))
+ if (TI)
Type = (Twine("' of type '") + TI->getType()->getAsString()).str();
Error(ValueLoc, "expected a list, got '" + I->getAsString() + Type + "'");
if (CurMultiClass)
@@ -2241,8 +2310,8 @@ VarInit *TGParser::ParseForeachDeclaration(ListInit *&ForeachListValue) {
"resolved at this time");
return nullptr;
}
- ForeachListValue = dyn_cast<ListInit>(I);
- IterType = ForeachListValue->getElementType();
+ ForeachListValue = I;
+ IterType = cast<ListRecTy>(TI->getType())->getElementType();
break;
}
}
@@ -2390,6 +2459,18 @@ bool TGParser::ApplyLetStack(Record *CurRec) {
return false;
}
+bool TGParser::ApplyLetStack(RecordsEntry &Entry) {
+ if (Entry.Rec)
+ return ApplyLetStack(Entry.Rec.get());
+
+ for (auto &E : Entry.Loop->Entries) {
+ if (ApplyLetStack(E))
+ return true;
+ }
+
+ return false;
+}
+
/// ParseObjectBody - Parse the body of a def or class. This consists of an
/// optional ClassList followed by a Body. CurRec is the current def or class
/// that is being parsed.
@@ -2451,7 +2532,7 @@ bool TGParser::ParseDef(MultiClass *CurMultiClass) {
if (ParseObjectBody(CurRec.get()))
return true;
- return addDef(std::move(CurRec));
+ return addEntry(std::move(CurRec));
}
/// ParseDefset - Parse a defset statement.
@@ -2508,12 +2589,13 @@ bool TGParser::ParseDefset() {
/// Foreach ::= FOREACH Declaration IN Object
///
bool TGParser::ParseForeach(MultiClass *CurMultiClass) {
+ SMLoc Loc = Lex.getLoc();
assert(Lex.getCode() == tgtok::Foreach && "Unknown tok");
Lex.Lex(); // Eat the 'for' token.
// Make a temporary object to record items associated with the for
// loop.
- ListInit *ListValue = nullptr;
+ Init *ListValue = nullptr;
VarInit *IterName = ParseForeachDeclaration(ListValue);
if (!IterName)
return TokError("expected declaration in for");
@@ -2523,7 +2605,7 @@ bool TGParser::ParseForeach(MultiClass *CurMultiClass) {
Lex.Lex(); // Eat the in
// Create a loop object and remember it.
- Loops.push_back(ForeachLoop(IterName, ListValue));
+ Loops.push_back(llvm::make_unique<ForeachLoop>(Loc, IterName, ListValue));
if (Lex.getCode() != tgtok::l_brace) {
// FOREACH Declaration IN Object
@@ -2545,10 +2627,11 @@ bool TGParser::ParseForeach(MultiClass *CurMultiClass) {
Lex.Lex(); // Eat the }
}
- // We've processed everything in this loop.
+ // Resolve the loop or store it for later resolution.
+ std::unique_ptr<ForeachLoop> Loop = std::move(Loops.back());
Loops.pop_back();
- return false;
+ return addEntry(std::move(Loop));
}
/// ParseClass - Parse a tblgen class definition.
@@ -2795,7 +2878,7 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
return TokError("expected ':' after defm identifier");
// Keep track of the new generated record definitions.
- SmallVector<std::unique_ptr<Record>, 8> NewRecDefs;
+ std::vector<RecordsEntry> NewEntries;
// This record also inherits from a regular class (non-multiclass)?
bool InheritFromClass = false;
@@ -2822,10 +2905,10 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
return Error(SubClassLoc,
"more template args specified than multiclass expects");
- SmallVector<std::pair<Init *, Init *>, 8> TemplateArgs;
+ SubstStack Substs;
for (unsigned i = 0, e = TArgs.size(); i != e; ++i) {
if (i < TemplateVals.size()) {
- TemplateArgs.emplace_back(TArgs[i], TemplateVals[i]);
+ Substs.emplace_back(TArgs[i], TemplateVals[i]);
} else {
Init *Default = MC->Rec.getValue(TArgs[i])->getValue();
if (!Default->isComplete()) {
@@ -2835,24 +2918,15 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
") of multiclass '" + MC->Rec.getNameInitAsString() +
"'");
}
- TemplateArgs.emplace_back(TArgs[i], Default);
+ Substs.emplace_back(TArgs[i], Default);
}
}
- TemplateArgs.emplace_back(QualifiedNameOfImplicitName(MC), DefmName);
-
- // Loop over all the def's in the multiclass, instantiating each one.
- for (const std::unique_ptr<Record> &DefProto : MC->DefPrototypes) {
- auto CurRec = make_unique<Record>(*DefProto);
- CurRec->appendLoc(SubClassLoc);
+ Substs.emplace_back(QualifiedNameOfImplicitName(MC), DefmName);
- MapResolver R(CurRec.get());
- for (const auto &TArg : TemplateArgs)
- R.set(TArg.first, TArg.second);
- CurRec->resolveReferences(R);
-
- NewRecDefs.emplace_back(std::move(CurRec));
- }
+ if (resolve(MC->Entries, Substs, CurMultiClass == nullptr, &NewEntries,
+ &SubClassLoc))
+ return true;
if (Lex.getCode() != tgtok::comma) break;
Lex.Lex(); // eat ','.
@@ -2882,9 +2956,9 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
// Get the expanded definition prototypes and teach them about
// the record values the current class to inherit has
- for (const auto &CurRec : NewRecDefs) {
+ for (auto &E : NewEntries) {
// Add it.
- if (AddSubClass(CurRec.get(), SubClass))
+ if (AddSubClass(E, SubClass))
return true;
}
@@ -2894,11 +2968,11 @@ bool TGParser::ParseDefm(MultiClass *CurMultiClass) {
}
}
- for (auto &CurRec : NewRecDefs) {
- if (ApplyLetStack(CurRec.get()))
+ for (auto &E : NewEntries) {
+ if (ApplyLetStack(E))
return true;
- addDef(std::move(CurRec));
+ addEntry(std::move(E));
}
if (Lex.getCode() != tgtok::semi)
@@ -2961,3 +3035,31 @@ bool TGParser::ParseFile() {
return TokError("Unexpected input at top level");
}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void RecordsEntry::dump() const {
+ if (Loop)
+ Loop->dump();
+ if (Rec)
+ Rec->dump();
+}
+
+LLVM_DUMP_METHOD void ForeachLoop::dump() const {
+ errs() << "foreach " << IterVar->getAsString() << " = "
+ << ListValue->getAsString() << " in {\n";
+
+ for (const auto &E : Entries)
+ E.dump();
+
+ errs() << "}\n";
+}
+
+LLVM_DUMP_METHOD void MultiClass::dump() const {
+ errs() << "Record:\n";
+ Rec.dump();
+
+ errs() << "Defs:\n";
+ for (const auto &E : Entries)
+ E.dump();
+}
+#endif
OpenPOWER on IntegriCloud