• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 the list.  However, if nodes are added to the list after the node being
38  * processed, some of the added nodes may not be processed.
39  */
40 ir_visitor_status
visit_list_elements(ir_hierarchical_visitor * v,exec_list * l)41 visit_list_elements(ir_hierarchical_visitor *v, exec_list *l)
42 {
43    ir_instruction *prev_base_ir = v->base_ir;
44 
45    foreach_list_safe(n, l) {
46       ir_instruction *const ir = (ir_instruction *) n;
47       v->base_ir = ir;
48       ir_visitor_status s = ir->accept(v);
49 
50       if (s != visit_continue)
51 	 return s;
52    }
53    v->base_ir = prev_base_ir;
54 
55    return visit_continue;
56 }
57 
58 
59 ir_visitor_status
accept(ir_hierarchical_visitor * v)60 ir_variable::accept(ir_hierarchical_visitor *v)
61 {
62    return v->visit(this);
63 }
64 
65 
66 ir_visitor_status
accept(ir_hierarchical_visitor * v)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
accept(ir_hierarchical_visitor * v)103 ir_loop_jump::accept(ir_hierarchical_visitor *v)
104 {
105    return v->visit(this);
106 }
107 
108 
109 ir_visitor_status
accept(ir_hierarchical_visitor * v)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->parameters);
117    if (s == visit_stop)
118       return s;
119 
120    s = visit_list_elements(v, &this->body);
121    return (s == visit_stop) ? s : v->visit_leave(this);
122 }
123 
124 
125 ir_visitor_status
accept(ir_hierarchical_visitor * v)126 ir_function::accept(ir_hierarchical_visitor *v)
127 {
128    ir_visitor_status s = v->visit_enter(this);
129    if (s != visit_continue)
130       return (s == visit_continue_with_parent) ? visit_continue : s;
131 
132    s = visit_list_elements(v, &this->signatures);
133    return (s == visit_stop) ? s : v->visit_leave(this);
134 }
135 
136 
137 ir_visitor_status
accept(ir_hierarchical_visitor * v)138 ir_expression::accept(ir_hierarchical_visitor *v)
139 {
140    ir_visitor_status s = v->visit_enter(this);
141 
142    if (s != visit_continue)
143       return (s == visit_continue_with_parent) ? visit_continue : s;
144 
145    for (unsigned i = 0; i < this->get_num_operands(); i++) {
146       switch (this->operands[i]->accept(v)) {
147       case visit_continue:
148 	 break;
149 
150       case visit_continue_with_parent:
151 	 // I wish for Java's labeled break-statement here.
152 	 goto done;
153 
154       case visit_stop:
155 	 return s;
156       }
157    }
158 
159 done:
160    return v->visit_leave(this);
161 }
162 
163 ir_visitor_status
accept(ir_hierarchical_visitor * v)164 ir_texture::accept(ir_hierarchical_visitor *v)
165 {
166    ir_visitor_status s = v->visit_enter(this);
167    if (s != visit_continue)
168       return (s == visit_continue_with_parent) ? visit_continue : s;
169 
170    s = this->sampler->accept(v);
171    if (s != visit_continue)
172       return (s == visit_continue_with_parent) ? visit_continue : s;
173 
174    s = this->coordinate->accept(v);
175    if (s != visit_continue)
176       return (s == visit_continue_with_parent) ? visit_continue : s;
177 
178    if (this->projector) {
179       s = this->projector->accept(v);
180       if (s != visit_continue)
181 	 return (s == visit_continue_with_parent) ? visit_continue : s;
182    }
183 
184    if (this->shadow_comparitor) {
185       s = this->shadow_comparitor->accept(v);
186       if (s != visit_continue)
187 	 return (s == visit_continue_with_parent) ? visit_continue : s;
188    }
189 
190    switch (this->op) {
191    case ir_tex:
192       break;
193    case ir_txb:
194       s = this->lod_info.bias->accept(v);
195       if (s != visit_continue)
196 	 return (s == visit_continue_with_parent) ? visit_continue : s;
197       break;
198    case ir_txl:
199    case ir_txf:
200       s = this->lod_info.lod->accept(v);
201       if (s != visit_continue)
202 	 return (s == visit_continue_with_parent) ? visit_continue : s;
203       break;
204    case ir_txd:
205       s = this->lod_info.grad.dPdx->accept(v);
206       if (s != visit_continue)
207 	 return (s == visit_continue_with_parent) ? visit_continue : s;
208 
209       s = this->lod_info.grad.dPdy->accept(v);
210       if (s != visit_continue)
211 	 return (s == visit_continue_with_parent) ? visit_continue : s;
212       break;
213    }
214 
215    return (s == visit_stop) ? s : v->visit_leave(this);
216 }
217 
218 
219 ir_visitor_status
accept(ir_hierarchical_visitor * v)220 ir_swizzle::accept(ir_hierarchical_visitor *v)
221 {
222    ir_visitor_status s = v->visit_enter(this);
223    if (s != visit_continue)
224       return (s == visit_continue_with_parent) ? visit_continue : s;
225 
226    s = this->val->accept(v);
227    return (s == visit_stop) ? s : v->visit_leave(this);
228 }
229 
230 
231 ir_visitor_status
accept(ir_hierarchical_visitor * v)232 ir_dereference_variable::accept(ir_hierarchical_visitor *v)
233 {
234    return v->visit(this);
235 }
236 
237 
238 ir_visitor_status
accept(ir_hierarchical_visitor * v)239 ir_dereference_array::accept(ir_hierarchical_visitor *v)
240 {
241    ir_visitor_status s = v->visit_enter(this);
242    if (s != visit_continue)
243       return (s == visit_continue_with_parent) ? visit_continue : s;
244 
245    /* The array index is not the target of the assignment, so clear the
246     * 'in_assignee' flag.  Restore it after returning from the array index.
247     */
248    const bool was_in_assignee = v->in_assignee;
249    v->in_assignee = false;
250    s = this->array_index->accept(v);
251    v->in_assignee = was_in_assignee;
252 
253    if (s != visit_continue)
254       return (s == visit_continue_with_parent) ? visit_continue : s;
255 
256    s = this->array->accept(v);
257    return (s == visit_stop) ? s : v->visit_leave(this);
258 }
259 
260 
261 ir_visitor_status
accept(ir_hierarchical_visitor * v)262 ir_dereference_record::accept(ir_hierarchical_visitor *v)
263 {
264    ir_visitor_status s = v->visit_enter(this);
265    if (s != visit_continue)
266       return (s == visit_continue_with_parent) ? visit_continue : s;
267 
268    s = this->record->accept(v);
269    return (s == visit_stop) ? s : v->visit_leave(this);
270 }
271 
272 
273 ir_visitor_status
accept(ir_hierarchical_visitor * v)274 ir_assignment::accept(ir_hierarchical_visitor *v)
275 {
276    ir_visitor_status s = v->visit_enter(this);
277    if (s != visit_continue)
278       return (s == visit_continue_with_parent) ? visit_continue : s;
279 
280    v->in_assignee = true;
281    s = this->lhs->accept(v);
282    v->in_assignee = false;
283    if (s != visit_continue)
284       return (s == visit_continue_with_parent) ? visit_continue : s;
285 
286    s = this->rhs->accept(v);
287    if (s != visit_continue)
288       return (s == visit_continue_with_parent) ? visit_continue : s;
289 
290    if (this->condition)
291       s = this->condition->accept(v);
292 
293    return (s == visit_stop) ? s : v->visit_leave(this);
294 }
295 
296 
297 ir_visitor_status
accept(ir_hierarchical_visitor * v)298 ir_constant::accept(ir_hierarchical_visitor *v)
299 {
300    return v->visit(this);
301 }
302 
303 
304 ir_visitor_status
accept(ir_hierarchical_visitor * v)305 ir_call::accept(ir_hierarchical_visitor *v)
306 {
307    ir_visitor_status s = v->visit_enter(this);
308    if (s != visit_continue)
309       return (s == visit_continue_with_parent) ? visit_continue : s;
310 
311    s = visit_list_elements(v, &this->actual_parameters);
312    if (s == visit_stop)
313       return s;
314 
315    return v->visit_leave(this);
316 }
317 
318 
319 ir_visitor_status
accept(ir_hierarchical_visitor * v)320 ir_return::accept(ir_hierarchical_visitor *v)
321 {
322    ir_visitor_status s = v->visit_enter(this);
323    if (s != visit_continue)
324       return (s == visit_continue_with_parent) ? visit_continue : s;
325 
326    ir_rvalue *val = this->get_value();
327    if (val) {
328       s = val->accept(v);
329       if (s != visit_continue)
330 	 return (s == visit_continue_with_parent) ? visit_continue : s;
331    }
332 
333    return v->visit_leave(this);
334 }
335 
336 
337 ir_visitor_status
accept(ir_hierarchical_visitor * v)338 ir_discard::accept(ir_hierarchical_visitor *v)
339 {
340    ir_visitor_status s = v->visit_enter(this);
341    if (s != visit_continue)
342       return (s == visit_continue_with_parent) ? visit_continue : s;
343 
344    if (this->condition != NULL) {
345       s = this->condition->accept(v);
346       if (s != visit_continue)
347 	 return (s == visit_continue_with_parent) ? visit_continue : s;
348    }
349 
350    return v->visit_leave(this);
351 }
352 
353 
354 ir_visitor_status
accept(ir_hierarchical_visitor * v)355 ir_if::accept(ir_hierarchical_visitor *v)
356 {
357    ir_visitor_status s = v->visit_enter(this);
358    if (s != visit_continue)
359       return (s == visit_continue_with_parent) ? visit_continue : s;
360 
361    s = this->condition->accept(v);
362    if (s != visit_continue)
363       return (s == visit_continue_with_parent) ? visit_continue : s;
364 
365    if (s != visit_continue_with_parent) {
366       s = visit_list_elements(v, &this->then_instructions);
367       if (s == visit_stop)
368 	 return s;
369    }
370 
371    if (s != visit_continue_with_parent) {
372       s = visit_list_elements(v, &this->else_instructions);
373       if (s == visit_stop)
374 	 return s;
375    }
376 
377    return v->visit_leave(this);
378 }
379