Nicolai Haehnle | 0715b9e | 2018-03-19 14:14:10 +0000 | [diff] [blame] | 1 | // RUN: llvm-tblgen %s | FileCheck %s |
| 2 | // XFAIL: vg_leak |
| 3 | |
| 4 | // CHECK: --- Defs --- |
| 5 | |
| 6 | // CHECK: def A0 { |
| 7 | // CHECK: dag a = (ops A0); |
| 8 | // CHECK: } |
| 9 | |
| 10 | // CHECK: def B0 { |
| 11 | // CHECK: dag a = (ops); |
| 12 | // CHECK: A b = B0; |
| 13 | // CHECK: } |
| 14 | |
| 15 | // CHECK: def C0 { |
| 16 | // CHECK: dag q = (ops C0); |
| 17 | // CHECK: } |
| 18 | |
Nicolai Haehnle | c9cc57b | 2018-03-19 14:14:20 +0000 | [diff] [blame] | 19 | // CHECK: def D0 { |
| 20 | // CHECK: D d = D0; |
| 21 | // CHECK: } |
| 22 | |
| 23 | // CHECK: def E0 { |
| 24 | // CHECK: E e = E0; |
| 25 | // CHECK: } |
| 26 | |
Nicolai Haehnle | 02dea26 | 2018-03-21 17:12:53 +0000 | [diff] [blame] | 27 | // CHECK: def F0 { |
| 28 | // CHECK: Fa as_a = F0; |
| 29 | // CHECK: Fb as_b = F0; |
| 30 | // CHECK: } |
| 31 | // CHECK: def F0x { |
| 32 | // CHECK: Fc as_c = F0; |
| 33 | // CHECK: } |
| 34 | |
Nicolai Haehnle | 0715b9e | 2018-03-19 14:14:10 +0000 | [diff] [blame] | 35 | def ops; |
| 36 | |
| 37 | class A<dag d> { |
| 38 | dag a = d; |
| 39 | } |
| 40 | |
| 41 | // This type of self-reference is used in various places defining register |
| 42 | // classes. |
| 43 | def A0 : A<(ops A0)>; |
| 44 | |
| 45 | class B<string self> { |
| 46 | A b = !cast<A>(self); |
| 47 | } |
| 48 | |
| 49 | // A stronger form of this type of self-reference is used at least in the |
| 50 | // SystemZ backend to define a record which is a ComplexPattern and an Operand |
| 51 | // at the same time. |
| 52 | def B0 : A<(ops)>, B<"B0">; |
| 53 | |
| 54 | // Casting C0 to C by name here is tricky, because it happens while (or rather: |
| 55 | // before) adding C as a superclass. However, SystemZ uses this pattern. |
| 56 | class C<string self> { |
| 57 | dag q = (ops !cast<C>(self)); |
| 58 | } |
| 59 | |
| 60 | def C0 : C<"C0">; |
Nicolai Haehnle | c9cc57b | 2018-03-19 14:14:20 +0000 | [diff] [blame] | 61 | |
| 62 | // Explore some unused corner cases. |
| 63 | // |
| 64 | // A self-reference within a class may seem icky, but it unavoidably falls out |
| 65 | // orthogonally of having forward class declarations and late resolve of self |
| 66 | // references. |
| 67 | class D<string self> { |
| 68 | D d = !cast<D>(self); |
| 69 | } |
| 70 | |
| 71 | def D0 : D<"D0">; |
| 72 | |
| 73 | class E<E x> { |
| 74 | E e = x; |
| 75 | } |
| 76 | |
| 77 | // Putting the !cast directly in the def should work as well: we shouldn't |
| 78 | // depend on implementation details of when exactly the record is looked up. |
| 79 | // |
| 80 | // Note the difference between !cast<E>("E0") and plain E0: the latter wouldn't |
| 81 | // work here because E0 does not yet have E as a superclass while the template |
| 82 | // arguments are being parsed. |
| 83 | def E0 : E<!cast<E>("E0")>; |
Nicolai Haehnle | 02dea26 | 2018-03-21 17:12:53 +0000 | [diff] [blame] | 84 | |
| 85 | // Ensure that records end up with the correct type even when direct self- |
| 86 | // references are involved. |
| 87 | class Fa; |
| 88 | class Fb<Fa x> { |
| 89 | Fa as_a = x; |
| 90 | } |
| 91 | class Fc<Fb x> { |
| 92 | Fb as_b = x; |
| 93 | } |
| 94 | |
| 95 | def F0 : Fa, Fb<F0>, Fc<F0>; |
| 96 | def F0x { |
| 97 | Fc as_c = F0; |
| 98 | } |