1// RUN: llvm-tblgen %s | FileCheck %s 2// RUN: not llvm-tblgen -DERROR1 %s 2>&1 | FileCheck --check-prefix=ERROR1 %s 3// RUN: not llvm-tblgen -DERROR2 %s 2>&1 | FileCheck --check-prefix=ERROR2 %s 4// RUN: not llvm-tblgen -DERROR3 %s 2>&1 | FileCheck --check-prefix=ERROR3 %s 5// RUN: not llvm-tblgen -DERROR4 %s 2>&1 | FileCheck --check-prefix=ERROR4 %s 6// RUN: not llvm-tblgen -DERROR5 %s 2>&1 | FileCheck --check-prefix=ERROR5 %s 7// RUN: not llvm-tblgen -DERROR6 %s 2>&1 | FileCheck --check-prefix=ERROR6 %s 8// RUN: not llvm-tblgen -DERROR7 %s 2>&1 | FileCheck --check-prefix=ERROR7 %s 9// RUN: not llvm-tblgen -DERROR8 %s 2>&1 | FileCheck --check-prefix=ERROR8 %s 10// RUN: not llvm-tblgen -DERROR9 %s 2>&1 | FileCheck --check-prefix=ERROR9 %s 11// RUN: not llvm-tblgen -DERROR10 %s 2>&1 | FileCheck --check-prefix=ERROR10 %s 12 13// !setop and !getop are deprecated in favor of !setdagop and !getdagop. 14// Two tests retain the old names just to be sure they are still supported. 15 16class Base; 17class OtherBase; 18 19class Super : Base; 20 21def foo: Base; 22def bar: Base; 23def qux: OtherBase; 24 25def alice : Super; 26def bob : Super; 27 28def test { 29 dag orig = (foo 1, 2:$a, $b); 30 dag another = (qux "hello", $world); 31 32 // CHECK: dag replaceWithBar = (bar 1, 2:$a, ?:$b); 33 dag replaceWithBar = !setop(orig, bar); 34 35 // CHECK: dag replaceWithBaz = (qux 1, 2:$a, ?:$b); 36 dag replaceWithBaz = !setdagop(orig, qux); 37 38 // CHECK: Base getopWithCast = foo; 39 Base getopWithCast = !getop<Base>(orig); 40 41 // CHECK: dag getopToSetop = (foo "hello", ?:$world); 42 dag getopToSetop = !setdagop(another, !getdagop(orig)); 43 44 // CHECK: dag getopToBangDag = (foo 1:$a, 2:$b, 3:$c); 45 dag getopToBangDag = !dag(!getdagop(orig), [1, 2, 3], ["a", "b", "c"]); 46 47 // CHECK: dag getopToDagInit = (foo "it worked"); 48 dag getopToDagInit = (!getdagop(orig) "it worked"); 49 50#ifdef ERROR1 51 // !getdagop(...) has a static type of 'any record at all, with no 52 // required superclasses'. That's too general to use in an 53 // assignment whose LHS demands an instance of Base, so we expect a 54 // static (parse-time) type-checking error. 55 56 // ERROR1: error: Field 'noCast' of type 'Base' is incompatible with value '!getdagop(orig)' of type '{}' 57 Base noCast = !getdagop(orig); 58#endif 59 60#ifdef ERROR2 61 // Here, we expect a _dynamic_ type error, when it turns out at 62 // evaluation time that the operator of 'another' is a record that 63 // isn't an instance of the specified base class. 64 65 // ERROR2: error: Expected type 'Base', got 'OtherBase' in: !getdagop((qux "hello", ?:$world)) 66 Base badCast = !getdagop<Base>(another); 67#endif 68 69#ifdef ERROR3 70 // Obviously, you shouldn't be able to give any type to !getdagop that 71 // isn't a class type. 72 73 // ERROR3: error: type for !getdagop must be a record type 74 int ridiculousCast = !getdagop<int>(orig); 75#endif 76 77 dag in1 = (foo 1:$a, 2:$b, 3:$c); 78 // CHECK: list<string> in1Names = ["a", "b", "c"]; 79 list<string> in1Names = !foreach(i, !range(!size(in1)), !getdagname(in1, i)); 80 // CHECK: list<int> in1Args = [1, 2, 3]; 81 list<int> in1Args = !foreach(i, !range(!size(in1)), !getdagarg<int>(in1, i)); 82 83 dag in2 = (foo 1:$a, (bar "x":$x, (qux foo:$s1, bar:$s2):$y, 7:$z):$b, 3:$c); 84 // CHECK: dag in2NestedDag = (qux foo:$s1, bar:$s2); 85 dag in2NestedDag = !getdagarg<dag>(!getdagarg<dag>(in2, 1), "y"); 86 // CHECK: Base in2NestedArg = foo; 87 Base in2NestedArg = !getdagarg<Base>(!getdagarg<dag>(!getdagarg<dag>(in2, 1), "y"), "s1"); 88 89 dag in3 = (foo 1:$a, ?:$b, 3); 90 // CHECK: list<string> in3Names = ["a", "b", ?]; 91 list<string> in3Names = !foreach(i, !range(!size(in3)), !getdagname(in3, i)); 92 // CHECK: list<int> in3Args = [1, ?, 3]; 93 list<int> in3Args = !foreach(i, !range(!size(in3)), !getdagarg<int>(in3, i)); 94 95#ifdef ERROR4 96 // ERROR4: error: !getdagarg index -1 is negative 97 int outOfRange = !getdagarg<int>(in1, -1); 98#endif 99 100#ifdef ERROR5 101 // ERROR5: error: !getdagarg index 3 is out of range (dag has 3 arguments) 102 int outOfRange = !getdagarg<int>(in1, 3); 103#endif 104 105#ifdef ERROR6 106 // ERROR6: error: !getdagarg key 'x' is not found 107 int notFound = !getdagarg<int>(in1, "x"); 108#endif 109 110 dag in4 = (foo "arg1":$a, "arg2":$b, "arg3":$c); 111 // CHECK: int misMatchType1 = ?; 112 int misMatchType1 = !getdagarg<int>(in4, 0); 113 114 dag in5 = (foo foo:$a, bar:$b, foo:$c); 115 // CHECK: OtherBase misMatchType2 = ?; 116 OtherBase misMatchType2 = !getdagarg<OtherBase>(in5, 1); 117 118 dag in6 = (foo alice:$a, bob:$b); 119 // CHECK: Base base = bob; 120 Base base = !getdagarg<Base>(in6, 1); 121 122 // CHECK: dag orig_set_val = (foo 1, 2:$a, "val":$b); 123 dag orig_set_val = !setdagarg(orig, 2, "val"); 124 // CHECK: dag orig_set_val_by_name = (foo 1, 2:$a, "aval":$b); 125 dag orig_set_val_by_name = !setdagarg(orig, "b", "aval"); 126 // CHECK: dag orig_set_dag_val = (foo 1, 2:$a, (bar foo:$p, qux:$q):$b); 127 dag orig_set_dag_val = !setdagarg(orig, "b", (bar foo:$p, qux:$q)); 128 // CHECK: dag orig_clr_val = (foo 1, ?:$a, ?:$b); 129 dag orig_clr_val = !setdagarg(orig, "a", ?); 130 // CHECK: dag orig_set_name = (foo 1:$c, 2:$a, ?:$b); 131 dag orig_set_name = !setdagname(orig, 0, "c"); 132 // CHECK: dag orig_clr_name = (foo 1, 2, ?:$b); 133 dag orig_clr_name = !setdagname(orig, 1, ?); 134 // CHECK: dag orig_rename = (foo 1, 2:$x, ?:$y); 135 dag orig_rename = !setdagname(!setdagname(orig, "a", "x"), "b", "y"); 136 137#ifdef ERROR7 138 // ERROR7: error: !setdagarg index -1 is negative 139 dag orig_negative = !setdagarg(orig, -1, "val"); 140#endif 141 142#ifdef ERROR8 143 // ERROR8: error: !setdagarg index 3 is out of range (dag has 3 arguments) 144 dag orig_out_of_range = !setdagarg(orig, 3, "val"); 145#endif 146 147#ifdef ERROR9 148 // ERROR9: error: expected integer index or string name, got type 'Base' 149 dag orig_out_of_range = !setdagarg(orig, foo, (foo qux:$a)); 150#endif 151} 152 153// Copy a list (Predicates) that is a field in a dag operator 154// (TestInstruction), which is defined in the same multiclass 155// (TestInstructionAndPattern) as the destination of the copy 156// (TestPattern::Predicates). 157class TestInstruction<list<int> _Predicates> { 158 list<int> Predicates = _Predicates; 159} 160#ifdef ERROR10 161class OtherTestInstruction<list<int> _Predicates> { 162 list<int> Predicates = _Predicates; 163} 164// ERROR10: error: Expected type 'OtherTestInstruction', got 'TestInstruction' 165class TestPattern<dag D> { 166 list<int> Predicates = !getdagop<OtherTestInstruction>(D).Predicates; 167} 168#else 169class TestPattern<dag D> { 170 list<int> Predicates = !getdagop<TestInstruction>(D).Predicates; 171} 172#endif 173 174multiclass TestInstructionAndPattern<list<int> Predicates> { 175 def NAME : TestInstruction<Predicates>; 176 def : TestPattern<(!cast<TestInstruction>(NAME) foo)>; 177} 178// CHECK: def testInst0 { // TestInstruction 179// CHECK-NEXT: list<int> Predicates = [7]; 180defm testInst0 : TestInstructionAndPattern<[7]>; 181