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 
24 #include "ir.h"
25 #include "ir_hierarchical_visitor.h"
26 
ir_hierarchical_visitor()27 ir_hierarchical_visitor::ir_hierarchical_visitor()
28 {
29    this->base_ir = NULL;
30    this->callback_enter = NULL;
31    this->callback_leave = NULL;
32    this->data_enter = NULL;
33    this->data_leave = NULL;
34    this->in_assignee = false;
35 }
36 
37 ir_visitor_status
visit(ir_rvalue * ir)38 ir_hierarchical_visitor::visit(ir_rvalue *ir)
39 {
40    call_enter_leave_callbacks(ir);
41 
42    return visit_continue;
43 }
44 
45 ir_visitor_status
visit(ir_variable * ir)46 ir_hierarchical_visitor::visit(ir_variable *ir)
47 {
48    call_enter_leave_callbacks(ir);
49 
50    return visit_continue;
51 }
52 
53 ir_visitor_status
visit(ir_constant * ir)54 ir_hierarchical_visitor::visit(ir_constant *ir)
55 {
56    call_enter_leave_callbacks(ir);
57 
58    return visit_continue;
59 }
60 
61 ir_visitor_status
visit(ir_loop_jump * ir)62 ir_hierarchical_visitor::visit(ir_loop_jump *ir)
63 {
64    call_enter_leave_callbacks(ir);
65 
66    return visit_continue;
67 }
68 
69 ir_visitor_status
visit(ir_dereference_variable * ir)70 ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
71 {
72    call_enter_leave_callbacks(ir);
73 
74    return visit_continue;
75 }
76 
77 ir_visitor_status
visit(ir_barrier * ir)78 ir_hierarchical_visitor::visit(ir_barrier *ir)
79 {
80    call_enter_leave_callbacks(ir);
81 
82    return visit_continue;
83 }
84 
85 ir_visitor_status
visit_enter(ir_loop * ir)86 ir_hierarchical_visitor::visit_enter(ir_loop *ir)
87 {
88    if (this->callback_enter != NULL)
89       this->callback_enter(ir, this->data_enter);
90 
91    return visit_continue;
92 }
93 
94 ir_visitor_status
visit_leave(ir_loop * ir)95 ir_hierarchical_visitor::visit_leave(ir_loop *ir)
96 {
97    if (this->callback_leave != NULL)
98       this->callback_leave(ir, this->data_leave);
99 
100    return visit_continue;
101 }
102 
103 ir_visitor_status
visit_enter(ir_function_signature * ir)104 ir_hierarchical_visitor::visit_enter(ir_function_signature *ir)
105 {
106    if (this->callback_enter != NULL)
107       this->callback_enter(ir, this->data_enter);
108 
109    return visit_continue;
110 }
111 
112 ir_visitor_status
visit_leave(ir_function_signature * ir)113 ir_hierarchical_visitor::visit_leave(ir_function_signature *ir)
114 {
115    if (this->callback_leave != NULL)
116       this->callback_leave(ir, this->data_leave);
117 
118    return visit_continue;
119 }
120 
121 ir_visitor_status
visit_enter(ir_function * ir)122 ir_hierarchical_visitor::visit_enter(ir_function *ir)
123 {
124    if (this->callback_enter != NULL)
125       this->callback_enter(ir, this->data_enter);
126 
127    return visit_continue;
128 }
129 
130 ir_visitor_status
visit_leave(ir_function * ir)131 ir_hierarchical_visitor::visit_leave(ir_function *ir)
132 {
133    if (this->callback_leave != NULL)
134       this->callback_leave(ir, this->data_leave);
135 
136    return visit_continue;
137 }
138 
139 ir_visitor_status
visit_enter(ir_expression * ir)140 ir_hierarchical_visitor::visit_enter(ir_expression *ir)
141 {
142    if (this->callback_enter != NULL)
143       this->callback_enter(ir, this->data_enter);
144 
145    return visit_continue;
146 }
147 
148 ir_visitor_status
visit_leave(ir_expression * ir)149 ir_hierarchical_visitor::visit_leave(ir_expression *ir)
150 {
151    if (this->callback_leave != NULL)
152       this->callback_leave(ir, this->data_leave);
153 
154    return visit_continue;
155 }
156 
157 ir_visitor_status
visit_enter(ir_texture * ir)158 ir_hierarchical_visitor::visit_enter(ir_texture *ir)
159 {
160    if (this->callback_enter != NULL)
161       this->callback_enter(ir, this->data_enter);
162 
163    return visit_continue;
164 }
165 
166 ir_visitor_status
visit_leave(ir_texture * ir)167 ir_hierarchical_visitor::visit_leave(ir_texture *ir)
168 {
169    if (this->callback_leave != NULL)
170       this->callback_leave(ir, this->data_leave);
171 
172    return visit_continue;
173 }
174 
175 ir_visitor_status
visit_enter(ir_swizzle * ir)176 ir_hierarchical_visitor::visit_enter(ir_swizzle *ir)
177 {
178    if (this->callback_enter != NULL)
179       this->callback_enter(ir, this->data_enter);
180 
181    return visit_continue;
182 }
183 
184 ir_visitor_status
visit_leave(ir_swizzle * ir)185 ir_hierarchical_visitor::visit_leave(ir_swizzle *ir)
186 {
187    if (this->callback_leave != NULL)
188       this->callback_leave(ir, this->data_leave);
189 
190    return visit_continue;
191 }
192 
193 ir_visitor_status
visit_enter(ir_dereference_array * ir)194 ir_hierarchical_visitor::visit_enter(ir_dereference_array *ir)
195 {
196    if (this->callback_enter != NULL)
197       this->callback_enter(ir, this->data_enter);
198 
199    return visit_continue;
200 }
201 
202 ir_visitor_status
visit_leave(ir_dereference_array * ir)203 ir_hierarchical_visitor::visit_leave(ir_dereference_array *ir)
204 {
205    if (this->callback_leave != NULL)
206       this->callback_leave(ir, this->data_leave);
207 
208    return visit_continue;
209 }
210 
211 ir_visitor_status
visit_enter(ir_dereference_record * ir)212 ir_hierarchical_visitor::visit_enter(ir_dereference_record *ir)
213 {
214    if (this->callback_enter != NULL)
215       this->callback_enter(ir, this->data_enter);
216 
217    return visit_continue;
218 }
219 
220 ir_visitor_status
visit_leave(ir_dereference_record * ir)221 ir_hierarchical_visitor::visit_leave(ir_dereference_record *ir)
222 {
223    if (this->callback_leave != NULL)
224       this->callback_leave(ir, this->data_leave);
225 
226    return visit_continue;
227 }
228 
229 ir_visitor_status
visit_enter(ir_assignment * ir)230 ir_hierarchical_visitor::visit_enter(ir_assignment *ir)
231 {
232    if (this->callback_enter != NULL)
233       this->callback_enter(ir, this->data_enter);
234 
235    return visit_continue;
236 }
237 
238 ir_visitor_status
visit_leave(ir_assignment * ir)239 ir_hierarchical_visitor::visit_leave(ir_assignment *ir)
240 {
241    if (this->callback_leave != NULL)
242       this->callback_leave(ir, this->data_leave);
243 
244    return visit_continue;
245 }
246 
247 ir_visitor_status
visit_enter(ir_call * ir)248 ir_hierarchical_visitor::visit_enter(ir_call *ir)
249 {
250    if (this->callback_enter != NULL)
251       this->callback_enter(ir, this->data_enter);
252 
253    return visit_continue;
254 }
255 
256 ir_visitor_status
visit_leave(ir_call * ir)257 ir_hierarchical_visitor::visit_leave(ir_call *ir)
258 {
259    if (this->callback_leave != NULL)
260       this->callback_leave(ir, this->data_leave);
261 
262    return visit_continue;
263 }
264 
265 ir_visitor_status
visit_enter(ir_return * ir)266 ir_hierarchical_visitor::visit_enter(ir_return *ir)
267 {
268    if (this->callback_enter != NULL)
269       this->callback_enter(ir, this->data_enter);
270 
271    return visit_continue;
272 }
273 
274 ir_visitor_status
visit_leave(ir_return * ir)275 ir_hierarchical_visitor::visit_leave(ir_return *ir)
276 {
277    if (this->callback_leave != NULL)
278       this->callback_leave(ir, this->data_leave);
279 
280    return visit_continue;
281 }
282 
283 ir_visitor_status
visit_enter(ir_discard * ir)284 ir_hierarchical_visitor::visit_enter(ir_discard *ir)
285 {
286    if (this->callback_enter != NULL)
287       this->callback_enter(ir, this->data_enter);
288 
289    return visit_continue;
290 }
291 
292 ir_visitor_status
visit_leave(ir_discard * ir)293 ir_hierarchical_visitor::visit_leave(ir_discard *ir)
294 {
295    if (this->callback_leave != NULL)
296       this->callback_leave(ir, this->data_leave);
297 
298    return visit_continue;
299 }
300 
301 ir_visitor_status
visit_enter(ir_demote * ir)302 ir_hierarchical_visitor::visit_enter(ir_demote *ir)
303 {
304    if (this->callback_enter != NULL)
305       this->callback_enter(ir, this->data_enter);
306 
307    return visit_continue;
308 }
309 
310 ir_visitor_status
visit_leave(ir_demote * ir)311 ir_hierarchical_visitor::visit_leave(ir_demote *ir)
312 {
313    if (this->callback_leave != NULL)
314       this->callback_leave(ir, this->data_leave);
315 
316    return visit_continue;
317 }
318 
319 ir_visitor_status
visit_enter(ir_if * ir)320 ir_hierarchical_visitor::visit_enter(ir_if *ir)
321 {
322    if (this->callback_enter != NULL)
323       this->callback_enter(ir, this->data_enter);
324 
325    return visit_continue;
326 }
327 
328 ir_visitor_status
visit_leave(ir_if * ir)329 ir_hierarchical_visitor::visit_leave(ir_if *ir)
330 {
331    if (this->callback_leave != NULL)
332       this->callback_leave(ir, this->data_leave);
333 
334    return visit_continue;
335 }
336 
337 ir_visitor_status
visit_enter(ir_emit_vertex * ir)338 ir_hierarchical_visitor::visit_enter(ir_emit_vertex *ir)
339 {
340    if (this->callback_enter != NULL)
341       this->callback_enter(ir, this->data_enter);
342 
343    return visit_continue;
344 }
345 
346 ir_visitor_status
visit_leave(ir_emit_vertex * ir)347 ir_hierarchical_visitor::visit_leave(ir_emit_vertex *ir)
348 {
349    if (this->callback_leave != NULL)
350       this->callback_leave(ir, this->data_leave);
351 
352    return visit_continue;
353 }
354 
355 ir_visitor_status
visit_enter(ir_end_primitive * ir)356 ir_hierarchical_visitor::visit_enter(ir_end_primitive *ir)
357 {
358    if (this->callback_enter != NULL)
359       this->callback_enter(ir, this->data_enter);
360 
361    return visit_continue;
362 }
363 
364 ir_visitor_status
visit_leave(ir_end_primitive * ir)365 ir_hierarchical_visitor::visit_leave(ir_end_primitive *ir)
366 {
367    if (this->callback_leave != NULL)
368       this->callback_leave(ir, this->data_leave);
369 
370    return visit_continue;
371 }
372 
373 void
run(exec_list * instructions)374 ir_hierarchical_visitor::run(exec_list *instructions)
375 {
376    visit_list_elements(this, instructions);
377 }
378 
379 void
call_enter_leave_callbacks(class ir_instruction * ir)380 ir_hierarchical_visitor::call_enter_leave_callbacks(class ir_instruction *ir)
381 {
382    if (this->callback_enter != NULL)
383       this->callback_enter(ir, this->data_enter);
384    if (this->callback_leave != NULL)
385       this->callback_leave(ir, this->data_leave);
386 }
387 
388 void
visit_tree(ir_instruction * ir,void (* callback_enter)(class ir_instruction * ir,void * data),void * data_enter,void (* callback_leave)(class ir_instruction * ir,void * data),void * data_leave)389 visit_tree(ir_instruction *ir,
390 	   void (*callback_enter)(class ir_instruction *ir, void *data),
391 	   void *data_enter,
392 	   void (*callback_leave)(class ir_instruction *ir, void *data),
393            void *data_leave)
394 {
395    ir_hierarchical_visitor v;
396 
397    v.callback_enter = callback_enter;
398    v.callback_leave = callback_leave;
399    v.data_enter = data_enter;
400    v.data_leave = data_leave;
401 
402    ir->accept(&v);
403 }
404