| // RUN: llvm-tblgen %s | FileCheck %s |
| // XFAIL: vg_leak |
| |
| // CHECK: --- Defs --- |
| |
| // CHECK: def A0 { |
| // CHECK: dag a = (ops A0); |
| // CHECK: } |
| |
| // CHECK: def B0 { |
| // CHECK: dag a = (ops); |
| // CHECK: A b = B0; |
| // CHECK: } |
| |
| // CHECK: def C0 { |
| // CHECK: dag q = (ops C0); |
| // CHECK: } |
| |
| // CHECK: def D0 { |
| // CHECK: D d = D0; |
| // CHECK: } |
| |
| // CHECK: def E0 { |
| // CHECK: E e = E0; |
| // CHECK: } |
| |
| // CHECK: def F0 { |
| // CHECK: Fa as_a = F0; |
| // CHECK: Fb as_b = F0; |
| // CHECK: } |
| // CHECK: def F0x { |
| // CHECK: Fc as_c = F0; |
| // CHECK: } |
| |
| // CHECK: def anonymous_0 { |
| // CHECK: G g = anonymous_0; |
| // CHECK: } |
| // CHECK: def anonymous_1 { |
| // CHECK: G g = anonymous_1; |
| // CHECK: } |
| // CHECK: def anonymous_2 { |
| // CHECK: G g = anonymous_2; |
| // CHECK: } |
| // CHECK: def anonymous_5 { |
| // CHECK: G g = anonymous_5; |
| // CHECK: } |
| |
| def ops; |
| |
| class A<dag d> { |
| dag a = d; |
| } |
| |
| // This type of self-reference is used in various places defining register |
| // classes. |
| def A0 : A<(ops A0)>; |
| |
| class B<string self> { |
| A b = !cast<A>(self); |
| } |
| |
| // A stronger form of this type of self-reference is used at least in the |
| // SystemZ backend to define a record which is a ComplexPattern and an Operand |
| // at the same time. |
| def B0 : A<(ops)>, B<"B0">; |
| |
| // Casting C0 to C by name here is tricky, because it happens while (or rather: |
| // before) adding C as a superclass. However, SystemZ uses this pattern. |
| class C<string self> { |
| dag q = (ops !cast<C>(self)); |
| } |
| |
| def C0 : C<"C0">; |
| |
| // Explore some unused corner cases. |
| // |
| // A self-reference within a class may seem icky, but it unavoidably falls out |
| // orthogonally of having forward class declarations and late resolve of self |
| // references. |
| class D<string self> { |
| D d = !cast<D>(self); |
| } |
| |
| def D0 : D<"D0">; |
| |
| class E<E x> { |
| E e = x; |
| } |
| |
| // Putting the !cast directly in the def should work as well: we shouldn't |
| // depend on implementation details of when exactly the record is looked up. |
| // |
| // Note the difference between !cast<E>("E0") and plain E0: the latter wouldn't |
| // work here because E0 does not yet have E as a superclass while the template |
| // arguments are being parsed. |
| def E0 : E<!cast<E>("E0")>; |
| |
| // Ensure that records end up with the correct type even when direct self- |
| // references are involved. |
| class Fa; |
| class Fb<Fa x> { |
| Fa as_a = x; |
| } |
| class Fc<Fb x> { |
| Fb as_b = x; |
| } |
| |
| def F0 : Fa, Fb<F0>, Fc<F0>; |
| def F0x { |
| Fc as_c = F0; |
| } |
| |
| // anonymous record self-reference in foreach and multiclass |
| class G { |
| G g = !cast<G>(NAME); |
| } |
| |
| foreach _ = [1, 2] in |
| def : G; |
| |
| multiclass H { |
| def : G; |
| } |
| |
| defm : H; |
| defm : H; |