xref: /llvm-project/llvm/test/TableGen/getsetop.td (revision fef2fc3400eb5a22a5ccc96bd3862bec0058d305)
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