updated some printfs, added comment about sched_yield
[mesa.git] / src / mesa / shader / slang / MachineIndependent / IntermTraverse.cpp
1 //
2 //Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 //All rights reserved.
4 //
5 //Redistribution and use in source and binary forms, with or without
6 //modification, are permitted provided that the following conditions
7 //are met:
8 //
9 // Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //
12 // Redistributions in binary form must reproduce the above
13 // copyright notice, this list of conditions and the following
14 // disclaimer in the documentation and/or other materials provided
15 // with the distribution.
16 //
17 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
18 // contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 //POSSIBILITY OF SUCH DAMAGE.
33 //
34
35 #include "../Include/intermediate.h"
36
37 //
38 // Traverse the intermediate representation tree, and
39 // call a node type specific function for each node.
40 // Done recursively through the member function Traverse().
41 // Node types can be skipped if their function to call is 0,
42 // but their subtree will still be traversed.
43 // Nodes with children can have their whole subtree skipped
44 // if preVisit is turned on and the type specific function
45 // returns false.
46 //
47 // preVisit, postVisit, and rightToLeft control what order
48 // nodes are visited in.
49 //
50
51 //
52 // Traversal functions for terminals are straighforward....
53 //
54 void TIntermSymbol::traverse(TIntermTraverser* it)
55 {
56 if (it->visitSymbol)
57 it->visitSymbol(this, it);
58 }
59
60 void TIntermConstantUnion::traverse(TIntermTraverser* it)
61 {
62 if (it->visitConstantUnion)
63 it->visitConstantUnion(this, it);
64 }
65
66 //
67 // Traverse a binary node.
68 //
69 void TIntermBinary::traverse(TIntermTraverser* it)
70 {
71 bool visit = true;
72
73 //
74 // visit the node before children if pre-visiting.
75 //
76 if (it->preVisit && it->visitBinary)
77 visit = it->visitBinary(true, this, it);
78
79 //
80 // Visit the children, in the right order.
81 //
82 if (visit) {
83 ++it->depth;
84 if (it->rightToLeft) {
85 if (right)
86 right->traverse(it);
87 if (left)
88 left->traverse(it);
89 } else {
90 if (left)
91 left->traverse(it);
92 if (right)
93 right->traverse(it);
94 }
95 --it->depth;
96 }
97
98 //
99 // Visit the node after the children, if requested and the traversal
100 // hasn't been cancelled yet.
101 //
102 if (visit && it->postVisit && it->visitBinary)
103 it->visitBinary(false, this, it);
104 }
105
106 //
107 // Traverse a unary node. Same comments in binary node apply here.
108 //
109 void TIntermUnary::traverse(TIntermTraverser* it)
110 {
111 bool visit = true;
112
113 if (it->preVisit && it->visitUnary)
114 visit = it->visitUnary(true, this, it);
115
116 if (visit) {
117 ++it->depth;
118 operand->traverse(it);
119 --it->depth;
120 }
121
122 if (visit && it->postVisit && it->visitUnary)
123 it->visitUnary(false, this, it);
124 }
125
126 //
127 // Traverse an aggregate node. Same comments in binary node apply here.
128 //
129 void TIntermAggregate::traverse(TIntermTraverser* it)
130 {
131 bool visit = true;
132
133 if (it->preVisit && it->visitAggregate)
134 visit = it->visitAggregate(true, this, it);
135
136 if (visit) {
137 ++it->depth;
138
139 TIntermSequence::iterator sit;
140 if (it->rightToLeft) {
141 sit = sequence.end();
142 while (sit != sequence.begin()) {
143 --sit;
144 (*sit)->traverse(it);
145 }
146 } else {
147 for (sit = sequence.begin(); sit != sequence.end(); ++sit)
148 (*sit)->traverse(it);
149 }
150
151 --it->depth;
152 }
153
154 if (visit && it->postVisit && it->visitAggregate)
155 it->visitAggregate(false, this, it);
156 }
157
158 //
159 // Traverse a selection node. Same comments in binary node apply here.
160 //
161 void TIntermSelection::traverse(TIntermTraverser* it)
162 {
163 bool visit = true;
164
165 if (it->preVisit && it->visitSelection)
166 visit = it->visitSelection(true, this, it);
167
168 if (visit) {
169 ++it->depth;
170 if (it->rightToLeft) {
171 if (falseBlock)
172 falseBlock->traverse(it);
173 if (trueBlock)
174 trueBlock->traverse(it);
175 condition->traverse(it);
176 } else {
177 condition->traverse(it);
178 if (trueBlock)
179 trueBlock->traverse(it);
180 if (falseBlock)
181 falseBlock->traverse(it);
182 }
183 --it->depth;
184 }
185
186 if (visit && it->postVisit && it->visitSelection)
187 it->visitSelection(false, this, it);
188 }
189
190 //
191 // Traverse a loop node. Same comments in binary node apply here.
192 //
193 void TIntermLoop::traverse(TIntermTraverser* it)
194 {
195 bool visit = true;
196
197 if (it->preVisit && it->visitLoop)
198 visit = it->visitLoop(true, this, it);
199
200 if (visit) {
201 ++it->depth;
202 if (it->rightToLeft) {
203 if (terminal)
204 terminal->traverse(it);
205 if (body)
206 body->traverse(it);
207 if (test)
208 test->traverse(it);
209 } else {
210 if (test)
211 test->traverse(it);
212 if (body)
213 body->traverse(it);
214 if (terminal)
215 terminal->traverse(it);
216 }
217 --it->depth;
218 }
219
220 if (visit && it->postVisit && it->visitLoop)
221 it->visitLoop(false, this, it);
222 }
223
224 //
225 // Traverse a branch node. Same comments in binary node apply here.
226 //
227 void TIntermBranch::traverse(TIntermTraverser* it)
228 {
229 bool visit = true;
230
231 if (it->preVisit && it->visitBranch)
232 visit = it->visitBranch(true, this, it);
233
234 if (visit && expression) {
235 ++it->depth;
236 expression->traverse(it);
237 --it->depth;
238 }
239
240 if (visit && it->postVisit && it->visitBranch)
241 it->visitBranch(false, this, it);
242 }
243