TableGen: Delay instantiating inline anonymous records
Summary:
Only instantiate anonymous records once all variable references in template
arguments have been resolved. This allows patterns like the new test case,
which in practice can appear in expressions like:
class IntrinsicTypeProfile<list<LLVMType> ty, int shift> {
list<LLVMType> types =
!listconcat(ty, [llvm_any_ty, LLVMMatchType<shift>]);
}
class FooIntrinsic<IntrinsicTypeProfile P, ...>
: Intrinsic<..., P.types, ...>;
Without this change, the anonymous LLVMMatchType instantiation would
never get resolved.
Another consequence of this change is that anonymous inline
instantiations are uniqued via the folding set of the newly introduced
VarDefInit.
Change-Id: I7a7041a20e297cf98c9109b28d85e64e176c932a
Reviewers: arsenm, craig.topper, tra, MartinO
Subscribers: wdng, llvm-commits
Differential Revision: https://reviews.llvm.org/D43756
llvm-svn: 326788
diff --git a/llvm/lib/TableGen/TGParser.cpp b/llvm/lib/TableGen/TGParser.cpp
index 642812d..654b4fd 100644
--- a/llvm/lib/TableGen/TGParser.cpp
+++ b/llvm/lib/TableGen/TGParser.cpp
@@ -1346,61 +1346,49 @@
return nullptr;
}
- SubClassReference SCRef;
- ParseValueList(SCRef.TemplateArgs, CurRec, Class);
- if (SCRef.TemplateArgs.empty()) return nullptr;
+ SmallVector<Init *, 8> Args;
+ ParseValueList(Args, CurRec, Class);
+ if (Args.empty()) return nullptr;
if (Lex.getCode() != tgtok::greater) {
TokError("expected '>' at end of value list");
return nullptr;
}
Lex.Lex(); // eat the '>'
- SMLoc EndLoc = Lex.getLoc();
- // Create the new record, set it as CurRec temporarily.
- auto NewRecOwner =
- make_unique<Record>(Records.getNewAnonymousName(), NameLoc, Records,
- /*IsAnonymous=*/true);
- Record *NewRec = NewRecOwner.get(); // Keep a copy since we may release.
- SCRef.RefRange = SMRange(NameLoc, EndLoc);
- SCRef.Rec = Class;
- // Add info about the subclass to NewRec.
- if (AddSubClass(NewRec, SCRef))
+ // Typecheck the template arguments list
+ ArrayRef<Init *> ExpectedArgs = Class->getTemplateArgs();
+ if (ExpectedArgs.size() < Args.size()) {
+ Error(NameLoc,
+ "More template args specified than expected");
return nullptr;
-
- if (!CurMultiClass) {
- NewRec->resolveReferences();
- Records.addDef(std::move(NewRecOwner));
- } else {
- // This needs to get resolved once the multiclass template arguments are
- // known before any use.
- NewRec->setResolveFirst(true);
- // Otherwise, we're inside a multiclass, add it to the multiclass.
- CurMultiClass->DefPrototypes.push_back(std::move(NewRecOwner));
-
- // Copy the template arguments for the multiclass into the def.
- for (Init *TArg : CurMultiClass->Rec.getTemplateArgs()) {
- const RecordVal *RV = CurMultiClass->Rec.getValue(TArg);
- assert(RV && "Template arg doesn't exist?");
- NewRec->addValue(*RV);
- }
-
- // We can't return the prototype def here, instead return:
- // !cast<ItemType>(!strconcat(NAME, AnonName)).
- const RecordVal *MCNameRV = CurMultiClass->Rec.getValue("NAME");
- assert(MCNameRV && "multiclass record must have a NAME");
-
- return UnOpInit::get(UnOpInit::CAST,
- BinOpInit::get(BinOpInit::STRCONCAT,
- VarInit::get(MCNameRV->getName(),
- MCNameRV->getType()),
- NewRec->getNameInit(),
- StringRecTy::get()),
- NewRec->getDefInit()->getType());
}
- // The result of the expression is a reference to the new record.
- return DefInit::get(NewRec);
+ for (unsigned i = 0, e = ExpectedArgs.size(); i != e; ++i) {
+ RecordVal *ExpectedArg = Class->getValue(ExpectedArgs[i]);
+ if (i < Args.size()) {
+ if (TypedInit *TI = dyn_cast<TypedInit>(Args[i])) {
+ RecTy *ExpectedType = ExpectedArg->getType();
+ if (!TI->getType()->typeIsConvertibleTo(ExpectedType)) {
+ Error(NameLoc,
+ "Value specified for template argument #" + Twine(i) + " (" +
+ ExpectedArg->getNameInitAsString() + ") is of type '" +
+ TI->getType()->getAsString() + "', expected '" +
+ ExpectedType->getAsString() + "': " + TI->getAsString());
+ return nullptr;
+ }
+ continue;
+ }
+ } else if (ExpectedArg->getValue()->isComplete())
+ continue;
+
+ Error(NameLoc,
+ "Value not specified for template argument #" + Twine(i) + " (" +
+ ExpectedArgs[i]->getAsUnquotedString() + ")");
+ return nullptr;
+ }
+
+ return VarDefInit::get(Class, Args)->Fold();
}
case tgtok::l_brace: { // Value ::= '{' ValueList '}'
SMLoc BraceLoc = Lex.getLoc();