Skip to content

Commit 193866b

Browse files
authored
[tblgen] Fix behavior of !isa to prevent premature folding (#130442)
The test included with this commit shows a case where, even though a record's true type was !isa<> some unrelated class, the isa<> operator wolud use the declared type of the argument it was examining in order to conclude that the !isa<> expression had to be be false. The issues is fixed by checking to make sure that the argument to the !isa operator is fully concrete before declaring its result to be false.
1 parent 1028ea9 commit 193866b

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

llvm/lib/TableGen/Record.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,10 +2115,12 @@ const Init *IsAOpInit::Fold() const {
21152115
return IntInit::get(getRecordKeeper(), 1);
21162116

21172117
if (isa<RecordRecTy>(CheckType)) {
2118-
// If the target type is not a subclass of the expression type, or if
2119-
// the expression has fully resolved to a record, we know that it can't
2120-
// be of the required type.
2121-
if (!CheckType->typeIsConvertibleTo(TI->getType()) || isa<DefInit>(Expr))
2118+
// If the target type is not a subclass of the expression type once the
2119+
// expression has been made concrete, or if the expression has fully
2120+
// resolved to a record, we know that it can't be of the required type.
2121+
if ((!CheckType->typeIsConvertibleTo(TI->getType()) &&
2122+
Expr->isConcrete()) ||
2123+
isa<DefInit>(Expr))
21222124
return IntInit::get(getRecordKeeper(), 0);
21232125
} else {
21242126
// We treat non-record types as not castable.

llvm/test/TableGen/isa-non-primary.td

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// RUN: llvm-tblgen %s | FileCheck %s
2+
3+
// CHECK: --- Defs ---
4+
// CHECK: def Op1 { // Op
5+
// CHECK-NEXT: string res = "yes";
6+
// CHECK-NEXT: }
7+
// CHECK: def Op2 { // Op
8+
// CHECK-NEXT: string res = "no";
9+
// CHECK-NEXT: }
10+
11+
class A<int a> {
12+
int x = a;
13+
}
14+
15+
class B<int a> : A<a> {
16+
bit y = 0;
17+
}
18+
19+
class C<int a> {
20+
int z = !add(a, 16);
21+
}
22+
23+
class D<int a> : B<a>, C<a>;
24+
25+
def E1 : D<5>;
26+
def E2 : B<2>;
27+
28+
class Op<A value> {
29+
string res = !if(!isa<C>(value), "yes", "no");
30+
}
31+
32+
def Op1 : Op<E1>;
33+
def Op2 : Op<E2>;

0 commit comments

Comments
 (0)