summaryrefslogtreecommitdiff
path: root/llvm/lib/TableGen
diff options
context:
space:
mode:
authorNicolai Haehnle <nhaehnle@gmail.com>2018-03-19 14:14:20 +0000
committerNicolai Haehnle <nhaehnle@gmail.com>2018-03-19 14:14:20 +0000
commit076f8dc78864a16d2823e21176833012a55081ce (patch)
tree90a9fb0dc9cabf5f4225f23c09b6ece8a7119734 /llvm/lib/TableGen
parent0d9fee1c146d47dbf280ab2f2fe87db44bc92dd5 (diff)
TableGen: Check the dynamic type of !cast<Rec>(string)
Summary: The docs already claim that this happens, but so far it hasn't. As a consequence, existing TableGen files get this wrong a lot, but luckily the fixes are all reasonably straightforward. To make this work with all the existing forms of self-references (since the true type of a record is only built up over time), the lookup of self-references in !cast is delayed until the final resolving step. Change-Id: If5923a72a252ba2fbc81a889d59775df0ef31164 Reviewers: arsenm, craig.topper, tra, MartinO Subscribers: wdng, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D44475
Diffstat (limited to 'llvm/lib/TableGen')
-rw-r--r--llvm/lib/TableGen/Record.cpp43
1 files changed, 33 insertions, 10 deletions
diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp
index 8b78f229ab3..333f45b7be9 100644
--- a/llvm/lib/TableGen/Record.cpp
+++ b/llvm/lib/TableGen/Record.cpp
@@ -194,7 +194,7 @@ void RecordRecTy::Profile(FoldingSetNodeID &ID) const {
std::string RecordRecTy::getAsString() const {
if (NumClasses == 1)
- return getClasses()[0]->getName();
+ return getClasses()[0]->getNameInitAsString();
std::string Str = "{";
bool First = true;
@@ -202,7 +202,7 @@ std::string RecordRecTy::getAsString() const {
if (!First)
Str += ", ";
First = false;
- Str += R->getName();
+ Str += R->getNameInitAsString();
}
Str += "}";
return Str;
@@ -700,7 +700,7 @@ void UnOpInit::Profile(FoldingSetNodeID &ID) const {
ProfileUnOpInit(ID, getOpcode(), getOperand(), getType());
}
-Init *UnOpInit::Fold(Record *CurRec) const {
+Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
switch (getOpcode()) {
case CAST:
if (isa<StringRecTy>(getType())) {
@@ -715,12 +715,34 @@ Init *UnOpInit::Fold(Record *CurRec) const {
} else if (isa<RecordRecTy>(getType())) {
if (StringInit *Name = dyn_cast<StringInit>(LHS)) {
assert(CurRec && "NULL pointer");
- if (Record *D = (CurRec->getRecords()).getDef(Name->getValue()))
- return DefInit::get(D);
+ Record *D;
+
+ // Self-references are allowed, but their resolution is delayed until
+ // the final resolve to ensure that we get the correct type for them.
+ if (Name == CurRec->getNameInit()) {
+ if (!IsFinal)
+ break;
+ D = CurRec;
+ } else {
+ D = CurRec->getRecords().getDef(Name->getValue());
+ if (!D) {
+ if (IsFinal)
+ PrintFatalError(CurRec->getLoc(),
+ Twine("Undefined reference to record: '") +
+ Name->getValue() + "'\n");
+ break;
+ }
+ }
- PrintFatalError(CurRec->getLoc(),
- Twine("Undefined reference to record: '") +
- Name->getValue() + "'\n");
+ DefInit *DI = DefInit::get(D);
+ if (!DI->getType()->typeIsA(getType())) {
+ PrintFatalError(CurRec->getLoc(),
+ Twine("Expected type '") +
+ getType()->getAsString() + "', got '" +
+ DI->getType()->getAsString() + "' in: " +
+ getAsString() + "\n");
+ }
+ return DI;
}
}
@@ -762,9 +784,9 @@ Init *UnOpInit::Fold(Record *CurRec) const {
Init *UnOpInit::resolveReferences(Resolver &R) const {
Init *lhs = LHS->resolveReferences(R);
- if (LHS != lhs)
+ if (LHS != lhs || (R.isFinal() && getOpcode() == CAST))
return (UnOpInit::get(getOpcode(), lhs, getType()))
- ->Fold(R.getCurrentRecord());
+ ->Fold(R.getCurrentRecord(), R.isFinal());
return const_cast<UnOpInit *>(this);
}
@@ -1904,6 +1926,7 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {
void Record::resolveReferences() {
RecordResolver R(*this);
+ R.setFinal(true);
resolveReferences(R);
}