glcpp: Accept #elif without an expression if the expression doesn't matter.
[mesa.git] / ir_hv_accept.cpp
1 /*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23 #define NULL 0
24 #include "ir.h"
25
26 /**
27 * \file ir_hv_accept.cpp
28 * Implementations of all hierarchical visitor accept methods for IR
29 * instructions.
30 */
31
32 /**
33 * Process a list of nodes using a hierarchical vistor
34 *
35 * \warning
36 * This function will operate correctly if a node being processed is removed
37 * from list. However, if nodes are added to the list after the node being
38 * processed, some of the added noded may not be processed.
39 */
40 static ir_visitor_status
41 visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
42 {
43 exec_node *next;
44
45 for (exec_node *n = l->head; n->next != NULL; n = next) {
46 next = n->next;
47
48 ir_instruction *const ir = (ir_instruction *) n;
49 ir_visitor_status s = ir->accept(v);
50
51 if (s != visit_continue)
52 return s;
53 }
54
55 return visit_continue;
56 }
57
58
59 ir_visitor_status
60 ir_variable::accept(ir_hierarchical_visitor *v)
61 {
62 return v->visit(this);
63 }
64
65
66 ir_visitor_status
67 ir_loop::accept(ir_hierarchical_visitor *v)
68 {
69 ir_visitor_status s = v->visit_enter(this);
70
71 if (s != visit_continue)
72 return (s == visit_continue_with_parent) ? visit_continue : s;
73
74 s = visit_list_elements(v, &this->body_instructions);
75 if (s == visit_stop)
76 return s;
77
78 if (s != visit_continue_with_parent) {
79 if (this->from) {
80 s = this->from->accept(v);
81 if (s != visit_continue)
82 return (s == visit_continue_with_parent) ? visit_continue : s;
83 }
84
85 if (this->to) {
86 s = this->to->accept(v);
87 if (s != visit_continue)
88 return (s == visit_continue_with_parent) ? visit_continue : s;
89 }
90
91 if (this->increment) {
92 s = this->increment->accept(v);
93 if (s != visit_continue)
94 return (s == visit_continue_with_parent) ? visit_continue : s;
95 }
96 }
97
98 return v->visit_leave(this);
99 }
100
101
102 ir_visitor_status
103 ir_loop_jump::accept(ir_hierarchical_visitor *v)
104 {
105 return v->visit(this);
106 }
107
108
109 ir_visitor_status
110 ir_function_signature::accept(ir_hierarchical_visitor *v)
111 {
112 ir_visitor_status s = v->visit_enter(this);
113 if (s != visit_continue)
114 return (s == visit_continue_with_parent) ? visit_continue : s;
115
116 s = visit_list_elements(v, &this->body);
117 return (s == visit_stop) ? s : v->visit_leave(this);
118 }
119
120
121 ir_visitor_status
122 ir_function::accept(ir_hierarchical_visitor *v)
123 {
124 ir_visitor_status s = v->visit_enter(this);
125 if (s != visit_continue)
126 return (s == visit_continue_with_parent) ? visit_continue : s;
127
128 s = visit_list_elements(v, &this->signatures);
129 return (s == visit_stop) ? s : v->visit_leave(this);
130 }
131
132
133 ir_visitor_status
134 ir_expression::accept(ir_hierarchical_visitor *v)
135 {
136 ir_visitor_status s = v->visit_enter(this);
137
138 if (s != visit_continue)
139 return (s == visit_continue_with_parent) ? visit_continue : s;
140
141 for (unsigned i = 0; i < this->get_num_operands(); i++) {
142 switch (this->operands[i]->accept(v)) {
143 case visit_continue:
144 break;
145
146 case visit_continue_with_parent:
147 // I wish for Java's labeled break-statement here.
148 goto done;
149
150 case visit_stop:
151 return s;
152 }
153 }
154
155 done:
156 return v->visit_leave(this);
157 }
158
159 ir_visitor_status
160 ir_texture::accept(ir_hierarchical_visitor *v)
161 {
162 return visit_continue_with_parent;
163 }
164
165
166 ir_visitor_status
167 ir_swizzle::accept(ir_hierarchical_visitor *v)
168 {
169 ir_visitor_status s = v->visit_enter(this);
170 if (s != visit_continue)
171 return (s == visit_continue_with_parent) ? visit_continue : s;
172
173 s = this->val->accept(v);
174 return (s == visit_stop) ? s : v->visit_leave(this);
175 }
176
177
178 ir_visitor_status
179 ir_dereference_variable::accept(ir_hierarchical_visitor *v)
180 {
181 return v->visit(this);
182 }
183
184
185 ir_visitor_status
186 ir_dereference_array::accept(ir_hierarchical_visitor *v)
187 {
188 ir_visitor_status s = v->visit_enter(this);
189 if (s != visit_continue)
190 return (s == visit_continue_with_parent) ? visit_continue : s;
191
192 s = this->array_index->accept(v);
193 if (s != visit_continue)
194 return (s == visit_continue_with_parent) ? visit_continue : s;
195
196 s = this->array->accept(v);
197 return (s == visit_stop) ? s : v->visit_leave(this);
198 }
199
200
201 ir_visitor_status
202 ir_dereference_record::accept(ir_hierarchical_visitor *v)
203 {
204 ir_visitor_status s = v->visit_enter(this);
205 if (s != visit_continue)
206 return (s == visit_continue_with_parent) ? visit_continue : s;
207
208 s = this->record->accept(v);
209 return (s == visit_stop) ? s : v->visit_leave(this);
210 }
211
212
213 ir_visitor_status
214 ir_assignment::accept(ir_hierarchical_visitor *v)
215 {
216 ir_visitor_status s = v->visit_enter(this);
217 if (s != visit_continue)
218 return (s == visit_continue_with_parent) ? visit_continue : s;
219
220 s = this->lhs->accept(v);
221 if (s != visit_continue)
222 return (s == visit_continue_with_parent) ? visit_continue : s;
223
224 s = this->rhs->accept(v);
225 if (s != visit_continue)
226 return (s == visit_continue_with_parent) ? visit_continue : s;
227
228 if (this->condition)
229 s = this->condition->accept(v);
230
231 return (s == visit_stop) ? s : v->visit_leave(this);
232 }
233
234
235 ir_visitor_status
236 ir_constant::accept(ir_hierarchical_visitor *v)
237 {
238 return v->visit(this);
239 }
240
241
242 ir_visitor_status
243 ir_call::accept(ir_hierarchical_visitor *v)
244 {
245 ir_visitor_status s = v->visit_enter(this);
246 if (s != visit_continue)
247 return (s == visit_continue_with_parent) ? visit_continue : s;
248
249 s = visit_list_elements(v, &this->actual_parameters);
250 if (s == visit_stop)
251 return s;
252
253 return v->visit_leave(this);
254 }
255
256
257 ir_visitor_status
258 ir_return::accept(ir_hierarchical_visitor *v)
259 {
260 ir_visitor_status s = v->visit_enter(this);
261 if (s != visit_continue)
262 return (s == visit_continue_with_parent) ? visit_continue : s;
263
264 ir_rvalue *val = this->get_value();
265 if (val) {
266 s = val->accept(v);
267 if (s != visit_continue)
268 return (s == visit_continue_with_parent) ? visit_continue : s;
269 }
270
271 return v->visit_leave(this);
272 }
273
274
275 ir_visitor_status
276 ir_if::accept(ir_hierarchical_visitor *v)
277 {
278 ir_visitor_status s = v->visit_enter(this);
279 if (s != visit_continue)
280 return (s == visit_continue_with_parent) ? visit_continue : s;
281
282 s = this->condition->accept(v);
283 if (s != visit_continue)
284 return (s == visit_continue_with_parent) ? visit_continue : s;
285
286 if (s != visit_continue_with_parent) {
287 s = visit_list_elements(v, &this->then_instructions);
288 if (s == visit_stop)
289 return s;
290 }
291
292 if (s != visit_continue_with_parent) {
293 s = visit_list_elements(v, &this->else_instructions);
294 if (s == visit_stop)
295 return s;
296 }
297
298 return v->visit_leave(this);
299 }