diff --git a/llvm/docs/TableGen/ProgRef.rst b/llvm/docs/TableGen/ProgRef.rst --- a/llvm/docs/TableGen/ProgRef.rst +++ b/llvm/docs/TableGen/ProgRef.rst @@ -1724,6 +1724,10 @@ This operator produces 1 if the type of *a* is a subtype of the given *type*; 0 otherwise. + If *a* is a string, then it is treated as a record name and looked up in + the list of all defined records. This operator produces 1 if we find the + record with that name; 0 otherwise. + ``!le(``\ *a*\ ``,`` *b*\ ``)`` This operator produces 1 if *a* is less than or equal to *b*; 0 otherwise. The arguments must be ``bit``, ``bits``, ``int``, or ``string`` values. diff --git a/llvm/include/llvm/TableGen/Record.h b/llvm/include/llvm/TableGen/Record.h --- a/llvm/include/llvm/TableGen/Record.h +++ b/llvm/include/llvm/TableGen/Record.h @@ -1084,7 +1084,7 @@ // Fold - If possible, fold this to a simpler init. Return this if not // possible to fold. - Init *Fold() const; + Init *Fold(bool IsFinal = false) const; bool isComplete() const override { return false; } diff --git a/llvm/lib/TableGen/Record.cpp b/llvm/lib/TableGen/Record.cpp --- a/llvm/lib/TableGen/Record.cpp +++ b/llvm/lib/TableGen/Record.cpp @@ -1623,13 +1623,28 @@ ProfileIsAOpInit(ID, CheckType, Expr); } -Init *IsAOpInit::Fold() const { +Init *IsAOpInit::Fold(bool IsFinal) const { if (TypedInit *TI = dyn_cast(Expr)) { // Is the expression type known to be (a subclass of) the desired type? if (TI->getType()->typeIsConvertibleTo(CheckType)) return IntInit::get(getRecordKeeper(), 1); if (isa(CheckType)) { + // If `Expr` is a string, we check if there is a record named `Expr`. If + // so, `Expr` is an instance of type `CheckType` and we return 1, or we + // return 0. + // We do this check until the final resolving step is done to match what + // !cast has done. + if (isa(TI->getType())) { + if (!IsFinal) + return const_cast(this); + return IntInit::get(getRecordKeeper(), + CheckType->getRecordKeeper().getDef( + cast(TI)->getAsUnquotedString()) + ? 1 + : 0); + } + // If the target type is not a subclass of the expression type, or if // the expression has fully resolved to a record, we know that it can't // be of the required type. @@ -1645,8 +1660,8 @@ Init *IsAOpInit::resolveReferences(Resolver &R) const { Init *NewExpr = Expr->resolveReferences(R); - if (Expr != NewExpr) - return get(CheckType, NewExpr)->Fold(); + if (Expr != NewExpr || R.isFinal()) + return get(CheckType, NewExpr)->Fold(R.isFinal()); return const_cast(this); } diff --git a/llvm/test/TableGen/isa.td b/llvm/test/TableGen/isa.td --- a/llvm/test/TableGen/isa.td +++ b/llvm/test/TableGen/isa.td @@ -19,6 +19,18 @@ // CHECK: int ret = 11; // CHECK: } +// CHECK: def Z0 { +// CHECK: int ret = 0; +// CHECK: } + +// CHECK: def Z1 { +// CHECK: int ret = 1; +// CHECK: } + +// CHECK: def Z2 { +// CHECK: int ret = -1; +// CHECK: } + class A; class B : A { int Num = num; @@ -32,8 +44,16 @@ int ret = !if(!isa(a), !cast(a).Num, 0); } +class Z { + int ret = !if(!isa("X" # id), !cast("X" # id).ret, -1); +} + def X0 : X>; def X1 : X>; def Y0 : Y>; def Y1 : Y>; + +def Z0: Z<0>; +def Z1: Z<1>; +def Z2: Z<2>;