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
27ir_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
37ir_visitor_status
38ir_hierarchical_visitor::visit(ir_rvalue *ir)
39{
40   call_enter_leave_callbacks(ir);
41
42   return visit_continue;
43}
44
45ir_visitor_status
46ir_hierarchical_visitor::visit(ir_variable *ir)
47{
48   call_enter_leave_callbacks(ir);
49
50   return visit_continue;
51}
52
53ir_visitor_status
54ir_hierarchical_visitor::visit(ir_constant *ir)
55{
56   call_enter_leave_callbacks(ir);
57
58   return visit_continue;
59}
60
61ir_visitor_status
62ir_hierarchical_visitor::visit(ir_loop_jump *ir)
63{
64   call_enter_leave_callbacks(ir);
65
66   return visit_continue;
67}
68
69ir_visitor_status
70ir_hierarchical_visitor::visit(ir_dereference_variable *ir)
71{
72   call_enter_leave_callbacks(ir);
73
74   return visit_continue;
75}
76
77ir_visitor_status
78ir_hierarchical_visitor::visit(ir_barrier *ir)
79{
80   call_enter_leave_callbacks(ir);
81
82   return visit_continue;
83}
84
85ir_visitor_status
86ir_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
94ir_visitor_status
95ir_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
103ir_visitor_status
104ir_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
112ir_visitor_status
113ir_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
121ir_visitor_status
122ir_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
130ir_visitor_status
131ir_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
139ir_visitor_status
140ir_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
148ir_visitor_status
149ir_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
157ir_visitor_status
158ir_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
166ir_visitor_status
167ir_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
175ir_visitor_status
176ir_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
184ir_visitor_status
185ir_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
193ir_visitor_status
194ir_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
202ir_visitor_status
203ir_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
211ir_visitor_status
212ir_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
220ir_visitor_status
221ir_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
229ir_visitor_status
230ir_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
238ir_visitor_status
239ir_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
247ir_visitor_status
248ir_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
256ir_visitor_status
257ir_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
265ir_visitor_status
266ir_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
274ir_visitor_status
275ir_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
283ir_visitor_status
284ir_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
292ir_visitor_status
293ir_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
301ir_visitor_status
302ir_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
310ir_visitor_status
311ir_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
319ir_visitor_status
320ir_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
328ir_visitor_status
329ir_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
337ir_visitor_status
338ir_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
346ir_visitor_status
347ir_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
355ir_visitor_status
356ir_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
364ir_visitor_status
365ir_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
373void
374ir_hierarchical_visitor::run(exec_list *instructions)
375{
376   visit_list_elements(this, instructions);
377}
378
379void
380ir_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
388void
389visit_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