1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2010 Intel Corporation
3b8e80941Smrg *
4b8e80941Smrg * Permission is hereby granted, free of charge, to any person obtaining a
5b8e80941Smrg * copy of this software and associated documentation files (the "Software"),
6b8e80941Smrg * to deal in the Software without restriction, including without limitation
7b8e80941Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b8e80941Smrg * and/or sell copies of the Software, and to permit persons to whom the
9b8e80941Smrg * Software is furnished to do so, subject to the following conditions:
10b8e80941Smrg *
11b8e80941Smrg * The above copyright notice and this permission notice (including the next
12b8e80941Smrg * paragraph) shall be included in all copies or substantial portions of the
13b8e80941Smrg * Software.
14b8e80941Smrg *
15b8e80941Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16b8e80941Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17b8e80941Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18b8e80941Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19b8e80941Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20b8e80941Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21b8e80941Smrg * DEALINGS IN THE SOFTWARE.
22b8e80941Smrg */
23b8e80941Smrg
24b8e80941Smrg#include "ir.h"
25b8e80941Smrg
26b8e80941Smrg/**
27b8e80941Smrg * \file ir_hv_accept.cpp
28b8e80941Smrg * Implementations of all hierarchical visitor accept methods for IR
29b8e80941Smrg * instructions.
30b8e80941Smrg */
31b8e80941Smrg
32b8e80941Smrg/**
33b8e80941Smrg * Process a list of nodes using a hierarchical vistor.
34b8e80941Smrg *
35b8e80941Smrg * If statement_list is true (the default), this is a list of statements, so
36b8e80941Smrg * v->base_ir will be set to point to each statement just before iterating
37b8e80941Smrg * over it, and restored after iteration is complete.  If statement_list is
38b8e80941Smrg * false, this is a list that appears inside a statement (e.g. a parameter
39b8e80941Smrg * list), so v->base_ir will be left alone.
40b8e80941Smrg *
41b8e80941Smrg * \warning
42b8e80941Smrg * This function will operate correctly if a node being processed is removed
43b8e80941Smrg * from the list.  However, if nodes are added to the list after the node being
44b8e80941Smrg * processed, some of the added nodes may not be processed.
45b8e80941Smrg */
46b8e80941Smrgir_visitor_status
47b8e80941Smrgvisit_list_elements(ir_hierarchical_visitor *v, exec_list *l,
48b8e80941Smrg                    bool statement_list)
49b8e80941Smrg{
50b8e80941Smrg   ir_instruction *prev_base_ir = v->base_ir;
51b8e80941Smrg
52b8e80941Smrg   foreach_in_list_safe(ir_instruction, ir, l) {
53b8e80941Smrg      if (statement_list)
54b8e80941Smrg         v->base_ir = ir;
55b8e80941Smrg      ir_visitor_status s = ir->accept(v);
56b8e80941Smrg
57b8e80941Smrg      if (s != visit_continue)
58b8e80941Smrg	 return s;
59b8e80941Smrg   }
60b8e80941Smrg   if (statement_list)
61b8e80941Smrg      v->base_ir = prev_base_ir;
62b8e80941Smrg
63b8e80941Smrg   return visit_continue;
64b8e80941Smrg}
65b8e80941Smrg
66b8e80941Smrg
67b8e80941Smrgir_visitor_status
68b8e80941Smrgir_rvalue::accept(ir_hierarchical_visitor *v)
69b8e80941Smrg{
70b8e80941Smrg   return v->visit(this);
71b8e80941Smrg}
72b8e80941Smrg
73b8e80941Smrg
74b8e80941Smrgir_visitor_status
75b8e80941Smrgir_variable::accept(ir_hierarchical_visitor *v)
76b8e80941Smrg{
77b8e80941Smrg   return v->visit(this);
78b8e80941Smrg}
79b8e80941Smrg
80b8e80941Smrg
81b8e80941Smrgir_visitor_status
82b8e80941Smrgir_loop::accept(ir_hierarchical_visitor *v)
83b8e80941Smrg{
84b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
85b8e80941Smrg
86b8e80941Smrg   if (s != visit_continue)
87b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
88b8e80941Smrg
89b8e80941Smrg   s = visit_list_elements(v, &this->body_instructions);
90b8e80941Smrg   if (s == visit_stop)
91b8e80941Smrg      return s;
92b8e80941Smrg
93b8e80941Smrg   return v->visit_leave(this);
94b8e80941Smrg}
95b8e80941Smrg
96b8e80941Smrg
97b8e80941Smrgir_visitor_status
98b8e80941Smrgir_loop_jump::accept(ir_hierarchical_visitor *v)
99b8e80941Smrg{
100b8e80941Smrg   return v->visit(this);
101b8e80941Smrg}
102b8e80941Smrg
103b8e80941Smrg
104b8e80941Smrgir_visitor_status
105b8e80941Smrgir_function_signature::accept(ir_hierarchical_visitor *v)
106b8e80941Smrg{
107b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
108b8e80941Smrg   if (s != visit_continue)
109b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
110b8e80941Smrg
111b8e80941Smrg   s = visit_list_elements(v, &this->parameters);
112b8e80941Smrg   if (s == visit_stop)
113b8e80941Smrg      return s;
114b8e80941Smrg
115b8e80941Smrg   s = visit_list_elements(v, &this->body);
116b8e80941Smrg   return (s == visit_stop) ? s : v->visit_leave(this);
117b8e80941Smrg}
118b8e80941Smrg
119b8e80941Smrg
120b8e80941Smrgir_visitor_status
121b8e80941Smrgir_function::accept(ir_hierarchical_visitor *v)
122b8e80941Smrg{
123b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
124b8e80941Smrg   if (s != visit_continue)
125b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
126b8e80941Smrg
127b8e80941Smrg   s = visit_list_elements(v, &this->signatures, false);
128b8e80941Smrg   return (s == visit_stop) ? s : v->visit_leave(this);
129b8e80941Smrg}
130b8e80941Smrg
131b8e80941Smrg
132b8e80941Smrgir_visitor_status
133b8e80941Smrgir_expression::accept(ir_hierarchical_visitor *v)
134b8e80941Smrg{
135b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
136b8e80941Smrg
137b8e80941Smrg   if (s != visit_continue)
138b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
139b8e80941Smrg
140b8e80941Smrg   for (unsigned i = 0; i < this->num_operands; i++) {
141b8e80941Smrg      switch (this->operands[i]->accept(v)) {
142b8e80941Smrg      case visit_continue:
143b8e80941Smrg	 break;
144b8e80941Smrg
145b8e80941Smrg      case visit_continue_with_parent:
146b8e80941Smrg	 // I wish for Java's labeled break-statement here.
147b8e80941Smrg	 goto done;
148b8e80941Smrg
149b8e80941Smrg      case visit_stop:
150b8e80941Smrg	 return visit_stop;
151b8e80941Smrg      }
152b8e80941Smrg   }
153b8e80941Smrg
154b8e80941Smrgdone:
155b8e80941Smrg   return v->visit_leave(this);
156b8e80941Smrg}
157b8e80941Smrg
158b8e80941Smrgir_visitor_status
159b8e80941Smrgir_texture::accept(ir_hierarchical_visitor *v)
160b8e80941Smrg{
161b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
162b8e80941Smrg   if (s != visit_continue)
163b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
164b8e80941Smrg
165b8e80941Smrg   s = this->sampler->accept(v);
166b8e80941Smrg   if (s != visit_continue)
167b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
168b8e80941Smrg
169b8e80941Smrg   if (this->coordinate) {
170b8e80941Smrg      s = this->coordinate->accept(v);
171b8e80941Smrg      if (s != visit_continue)
172b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
173b8e80941Smrg   }
174b8e80941Smrg
175b8e80941Smrg   if (this->projector) {
176b8e80941Smrg      s = this->projector->accept(v);
177b8e80941Smrg      if (s != visit_continue)
178b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
179b8e80941Smrg   }
180b8e80941Smrg
181b8e80941Smrg   if (this->shadow_comparator) {
182b8e80941Smrg      s = this->shadow_comparator->accept(v);
183b8e80941Smrg      if (s != visit_continue)
184b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
185b8e80941Smrg   }
186b8e80941Smrg
187b8e80941Smrg   if (this->offset) {
188b8e80941Smrg      s = this->offset->accept(v);
189b8e80941Smrg      if (s != visit_continue)
190b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
191b8e80941Smrg   }
192b8e80941Smrg
193b8e80941Smrg   switch (this->op) {
194b8e80941Smrg   case ir_tex:
195b8e80941Smrg   case ir_lod:
196b8e80941Smrg   case ir_query_levels:
197b8e80941Smrg   case ir_texture_samples:
198b8e80941Smrg   case ir_samples_identical:
199b8e80941Smrg      break;
200b8e80941Smrg   case ir_txb:
201b8e80941Smrg      s = this->lod_info.bias->accept(v);
202b8e80941Smrg      if (s != visit_continue)
203b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
204b8e80941Smrg      break;
205b8e80941Smrg   case ir_txl:
206b8e80941Smrg   case ir_txf:
207b8e80941Smrg   case ir_txs:
208b8e80941Smrg      s = this->lod_info.lod->accept(v);
209b8e80941Smrg      if (s != visit_continue)
210b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
211b8e80941Smrg      break;
212b8e80941Smrg   case ir_txf_ms:
213b8e80941Smrg      s = this->lod_info.sample_index->accept(v);
214b8e80941Smrg      if (s != visit_continue)
215b8e80941Smrg         return (s == visit_continue_with_parent) ? visit_continue : s;
216b8e80941Smrg      break;
217b8e80941Smrg   case ir_txd:
218b8e80941Smrg      s = this->lod_info.grad.dPdx->accept(v);
219b8e80941Smrg      if (s != visit_continue)
220b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
221b8e80941Smrg
222b8e80941Smrg      s = this->lod_info.grad.dPdy->accept(v);
223b8e80941Smrg      if (s != visit_continue)
224b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
225b8e80941Smrg      break;
226b8e80941Smrg   case ir_tg4:
227b8e80941Smrg      s = this->lod_info.component->accept(v);
228b8e80941Smrg      if (s != visit_continue)
229b8e80941Smrg         return (s == visit_continue_with_parent) ? visit_continue : s;
230b8e80941Smrg      break;
231b8e80941Smrg   }
232b8e80941Smrg
233b8e80941Smrg   assert(s == visit_continue);
234b8e80941Smrg   return v->visit_leave(this);
235b8e80941Smrg}
236b8e80941Smrg
237b8e80941Smrg
238b8e80941Smrgir_visitor_status
239b8e80941Smrgir_swizzle::accept(ir_hierarchical_visitor *v)
240b8e80941Smrg{
241b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
242b8e80941Smrg   if (s != visit_continue)
243b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
244b8e80941Smrg
245b8e80941Smrg   s = this->val->accept(v);
246b8e80941Smrg   return (s == visit_stop) ? s : v->visit_leave(this);
247b8e80941Smrg}
248b8e80941Smrg
249b8e80941Smrg
250b8e80941Smrgir_visitor_status
251b8e80941Smrgir_dereference_variable::accept(ir_hierarchical_visitor *v)
252b8e80941Smrg{
253b8e80941Smrg   return v->visit(this);
254b8e80941Smrg}
255b8e80941Smrg
256b8e80941Smrg
257b8e80941Smrgir_visitor_status
258b8e80941Smrgir_dereference_array::accept(ir_hierarchical_visitor *v)
259b8e80941Smrg{
260b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
261b8e80941Smrg   if (s != visit_continue)
262b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
263b8e80941Smrg
264b8e80941Smrg   /* The array index is not the target of the assignment, so clear the
265b8e80941Smrg    * 'in_assignee' flag.  Restore it after returning from the array index.
266b8e80941Smrg    */
267b8e80941Smrg   const bool was_in_assignee = v->in_assignee;
268b8e80941Smrg   v->in_assignee = false;
269b8e80941Smrg   s = this->array_index->accept(v);
270b8e80941Smrg   v->in_assignee = was_in_assignee;
271b8e80941Smrg
272b8e80941Smrg   if (s != visit_continue)
273b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
274b8e80941Smrg
275b8e80941Smrg   s = this->array->accept(v);
276b8e80941Smrg   return (s == visit_stop) ? s : v->visit_leave(this);
277b8e80941Smrg}
278b8e80941Smrg
279b8e80941Smrg
280b8e80941Smrgir_visitor_status
281b8e80941Smrgir_dereference_record::accept(ir_hierarchical_visitor *v)
282b8e80941Smrg{
283b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
284b8e80941Smrg   if (s != visit_continue)
285b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
286b8e80941Smrg
287b8e80941Smrg   s = this->record->accept(v);
288b8e80941Smrg   return (s == visit_stop) ? s : v->visit_leave(this);
289b8e80941Smrg}
290b8e80941Smrg
291b8e80941Smrg
292b8e80941Smrgir_visitor_status
293b8e80941Smrgir_assignment::accept(ir_hierarchical_visitor *v)
294b8e80941Smrg{
295b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
296b8e80941Smrg   if (s != visit_continue)
297b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
298b8e80941Smrg
299b8e80941Smrg   v->in_assignee = true;
300b8e80941Smrg   s = this->lhs->accept(v);
301b8e80941Smrg   v->in_assignee = false;
302b8e80941Smrg   if (s != visit_continue)
303b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
304b8e80941Smrg
305b8e80941Smrg   s = this->rhs->accept(v);
306b8e80941Smrg   if (s != visit_continue)
307b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
308b8e80941Smrg
309b8e80941Smrg   if (this->condition)
310b8e80941Smrg      s = this->condition->accept(v);
311b8e80941Smrg
312b8e80941Smrg   return (s == visit_stop) ? s : v->visit_leave(this);
313b8e80941Smrg}
314b8e80941Smrg
315b8e80941Smrg
316b8e80941Smrgir_visitor_status
317b8e80941Smrgir_constant::accept(ir_hierarchical_visitor *v)
318b8e80941Smrg{
319b8e80941Smrg   return v->visit(this);
320b8e80941Smrg}
321b8e80941Smrg
322b8e80941Smrg
323b8e80941Smrgir_visitor_status
324b8e80941Smrgir_call::accept(ir_hierarchical_visitor *v)
325b8e80941Smrg{
326b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
327b8e80941Smrg   if (s != visit_continue)
328b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
329b8e80941Smrg
330b8e80941Smrg   if (this->return_deref != NULL) {
331b8e80941Smrg      v->in_assignee = true;
332b8e80941Smrg      s = this->return_deref->accept(v);
333b8e80941Smrg      v->in_assignee = false;
334b8e80941Smrg      if (s != visit_continue)
335b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
336b8e80941Smrg   }
337b8e80941Smrg
338b8e80941Smrg   s = visit_list_elements(v, &this->actual_parameters, false);
339b8e80941Smrg   if (s == visit_stop)
340b8e80941Smrg      return s;
341b8e80941Smrg
342b8e80941Smrg   return v->visit_leave(this);
343b8e80941Smrg}
344b8e80941Smrg
345b8e80941Smrg
346b8e80941Smrgir_visitor_status
347b8e80941Smrgir_return::accept(ir_hierarchical_visitor *v)
348b8e80941Smrg{
349b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
350b8e80941Smrg   if (s != visit_continue)
351b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
352b8e80941Smrg
353b8e80941Smrg   ir_rvalue *val = this->get_value();
354b8e80941Smrg   if (val) {
355b8e80941Smrg      s = val->accept(v);
356b8e80941Smrg      if (s != visit_continue)
357b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
358b8e80941Smrg   }
359b8e80941Smrg
360b8e80941Smrg   return v->visit_leave(this);
361b8e80941Smrg}
362b8e80941Smrg
363b8e80941Smrg
364b8e80941Smrgir_visitor_status
365b8e80941Smrgir_discard::accept(ir_hierarchical_visitor *v)
366b8e80941Smrg{
367b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
368b8e80941Smrg   if (s != visit_continue)
369b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
370b8e80941Smrg
371b8e80941Smrg   if (this->condition != NULL) {
372b8e80941Smrg      s = this->condition->accept(v);
373b8e80941Smrg      if (s != visit_continue)
374b8e80941Smrg	 return (s == visit_continue_with_parent) ? visit_continue : s;
375b8e80941Smrg   }
376b8e80941Smrg
377b8e80941Smrg   return v->visit_leave(this);
378b8e80941Smrg}
379b8e80941Smrg
380b8e80941Smrg
381b8e80941Smrgir_visitor_status
382b8e80941Smrgir_if::accept(ir_hierarchical_visitor *v)
383b8e80941Smrg{
384b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
385b8e80941Smrg   if (s != visit_continue)
386b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
387b8e80941Smrg
388b8e80941Smrg   s = this->condition->accept(v);
389b8e80941Smrg   if (s != visit_continue)
390b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
391b8e80941Smrg
392b8e80941Smrg   if (s != visit_continue_with_parent) {
393b8e80941Smrg      s = visit_list_elements(v, &this->then_instructions);
394b8e80941Smrg      if (s == visit_stop)
395b8e80941Smrg	 return s;
396b8e80941Smrg   }
397b8e80941Smrg
398b8e80941Smrg   if (s != visit_continue_with_parent) {
399b8e80941Smrg      s = visit_list_elements(v, &this->else_instructions);
400b8e80941Smrg      if (s == visit_stop)
401b8e80941Smrg	 return s;
402b8e80941Smrg   }
403b8e80941Smrg
404b8e80941Smrg   return v->visit_leave(this);
405b8e80941Smrg}
406b8e80941Smrg
407b8e80941Smrgir_visitor_status
408b8e80941Smrgir_emit_vertex::accept(ir_hierarchical_visitor *v)
409b8e80941Smrg{
410b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
411b8e80941Smrg   if (s != visit_continue)
412b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
413b8e80941Smrg
414b8e80941Smrg   s = this->stream->accept(v);
415b8e80941Smrg   if (s != visit_continue)
416b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
417b8e80941Smrg
418b8e80941Smrg   assert(s == visit_continue);
419b8e80941Smrg   return v->visit_leave(this);
420b8e80941Smrg}
421b8e80941Smrg
422b8e80941Smrg
423b8e80941Smrgir_visitor_status
424b8e80941Smrgir_end_primitive::accept(ir_hierarchical_visitor *v)
425b8e80941Smrg{
426b8e80941Smrg   ir_visitor_status s = v->visit_enter(this);
427b8e80941Smrg   if (s != visit_continue)
428b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
429b8e80941Smrg
430b8e80941Smrg   s = this->stream->accept(v);
431b8e80941Smrg   if (s != visit_continue)
432b8e80941Smrg      return (s == visit_continue_with_parent) ? visit_continue : s;
433b8e80941Smrg
434b8e80941Smrg   assert(s == visit_continue);
435b8e80941Smrg   return v->visit_leave(this);
436b8e80941Smrg}
437b8e80941Smrg
438b8e80941Smrgir_visitor_status
439b8e80941Smrgir_barrier::accept(ir_hierarchical_visitor *v)
440b8e80941Smrg{
441b8e80941Smrg   return v->visit(this);
442b8e80941Smrg}
443