blob: 360f1ce3834f50e310add49832218887057008ba [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7#include "localintermediate.h"
8
9//
10// Two purposes:
11// 1. Show an example of how to iterate tree. Functions can
12// also directly call Traverse() on children themselves to
13// have finer grained control over the process than shown here.
14// See the last function for how to get started.
15// 2. Print out a text based description of the tree.
16//
17
18//
19// Use this class to carry along data from node to node in
20// the traversal
21//
22class TOutputTraverser : public TIntermTraverser {
23public:
alokp@chromium.org76b82082010-03-24 17:59:39 +000024 TOutputTraverser(TInfoSink& i) : infoSink(i) { }
25 TInfoSink& infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026
27protected:
alokp@chromium.org76b82082010-03-24 17:59:39 +000028 void visitSymbol(TIntermSymbol*);
29 void visitConstantUnion(TIntermConstantUnion*);
30 bool visitBinary(Visit visit, TIntermBinary*);
31 bool visitUnary(Visit visit, TIntermUnary*);
32 bool visitSelection(Visit visit, TIntermSelection*);
33 bool visitAggregate(Visit visit, TIntermAggregate*);
34 bool visitLoop(Visit visit, TIntermLoop*);
35 bool visitBranch(Visit visit, TIntermBranch*);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036};
37
38TString TType::getCompleteString() const
39{
alokp@chromium.org76b82082010-03-24 17:59:39 +000040 char buf[100];
41 char *p = &buf[0];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042
alokp@chromium.org76b82082010-03-24 17:59:39 +000043 if (qualifier != EvqTemporary && qualifier != EvqGlobal)
44 p += sprintf(p, "%s ", getQualifierString());
45 if (array)
46 p += sprintf(p, "array of ");
47 if (matrix)
48 p += sprintf(p, "%dX%d matrix of ", size, size);
49 else if (size > 1)
50 p += sprintf(p, "%d-component vector of ", size);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051
alokp@chromium.org76b82082010-03-24 17:59:39 +000052 sprintf(p, "%s", getBasicString());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000053
alokp@chromium.org76b82082010-03-24 17:59:39 +000054 return TString(buf);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055}
56
57//
58// Helper functions for printing, not part of traversing.
59//
60
61void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
62{
alokp@chromium.org76b82082010-03-24 17:59:39 +000063 int i;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064
alokp@chromium.org76b82082010-03-24 17:59:39 +000065 infoSink.debug << FormatSourceLoc(node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066
alokp@chromium.org76b82082010-03-24 17:59:39 +000067 for (i = 0; i < depth; ++i)
68 infoSink.debug << " ";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069}
70
71//
72// The rest of the file are the traversal functions. The last one
73// is the one that starts the traversal.
74//
75// Return true from interior nodes to have the external traversal
76// continue on to children. If you process children yourself,
77// return false.
78//
79
80void TOutputTraverser::visitSymbol(TIntermSymbol* node)
81{
alokp@chromium.org76b82082010-03-24 17:59:39 +000082 OutputTreeText(infoSink, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083
alokp@chromium.org76b82082010-03-24 17:59:39 +000084 char buf[100];
85 sprintf(buf, "'%s' (%s)\n",
86 node->getSymbol().c_str(),
87 node->getCompleteString().c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088
alokp@chromium.org76b82082010-03-24 17:59:39 +000089 infoSink.debug << buf;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090}
91
92bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
93{
alokp@chromium.org76b82082010-03-24 17:59:39 +000094 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
alokp@chromium.org76b82082010-03-24 17:59:39 +000096 OutputTreeText(out, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097
alokp@chromium.org76b82082010-03-24 17:59:39 +000098 switch (node->getOp()) {
99 case EOpAssign: out.debug << "move second child to first child"; break;
100 case EOpInitialize: out.debug << "initialize first child with second child"; break;
101 case EOpAddAssign: out.debug << "add second child into first child"; break;
102 case EOpSubAssign: out.debug << "subtract second child into first child"; break;
103 case EOpMulAssign: out.debug << "multiply second child into first child"; break;
104 case EOpVectorTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
105 case EOpVectorTimesScalarAssign: out.debug << "vector scale second child into first child"; break;
106 case EOpMatrixTimesScalarAssign: out.debug << "matrix scale second child into first child"; break;
107 case EOpMatrixTimesMatrixAssign: out.debug << "matrix mult second child into first child"; break;
108 case EOpDivAssign: out.debug << "divide second child into first child"; break;
109 case EOpIndexDirect: out.debug << "direct index"; break;
110 case EOpIndexIndirect: out.debug << "indirect index"; break;
111 case EOpIndexDirectStruct: out.debug << "direct index for structure"; break;
112 case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113
alokp@chromium.org76b82082010-03-24 17:59:39 +0000114 case EOpAdd: out.debug << "add"; break;
115 case EOpSub: out.debug << "subtract"; break;
116 case EOpMul: out.debug << "component-wise multiply"; break;
117 case EOpDiv: out.debug << "divide"; break;
118 case EOpEqual: out.debug << "Compare Equal"; break;
119 case EOpNotEqual: out.debug << "Compare Not Equal"; break;
120 case EOpLessThan: out.debug << "Compare Less Than"; break;
121 case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
122 case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
123 case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124
alokp@chromium.org76b82082010-03-24 17:59:39 +0000125 case EOpVectorTimesScalar: out.debug << "vector-scale"; break;
126 case EOpVectorTimesMatrix: out.debug << "vector-times-matrix"; break;
127 case EOpMatrixTimesVector: out.debug << "matrix-times-vector"; break;
128 case EOpMatrixTimesScalar: out.debug << "matrix-scale"; break;
129 case EOpMatrixTimesMatrix: out.debug << "matrix-multiply"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130
alokp@chromium.org76b82082010-03-24 17:59:39 +0000131 case EOpLogicalOr: out.debug << "logical-or"; break;
132 case EOpLogicalXor: out.debug << "logical-xor"; break;
133 case EOpLogicalAnd: out.debug << "logical-and"; break;
134 default: out.debug << "<unknown op>";
135 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
alokp@chromium.org76b82082010-03-24 17:59:39 +0000137 out.debug << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138
alokp@chromium.org76b82082010-03-24 17:59:39 +0000139 out.debug << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
alokp@chromium.org76b82082010-03-24 17:59:39 +0000141 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142}
143
144bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
145{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000146 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147
alokp@chromium.org76b82082010-03-24 17:59:39 +0000148 OutputTreeText(out, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149
alokp@chromium.org76b82082010-03-24 17:59:39 +0000150 switch (node->getOp()) {
151 case EOpNegative: out.debug << "Negate value"; break;
152 case EOpVectorLogicalNot:
153 case EOpLogicalNot: out.debug << "Negate conditional"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154
alokp@chromium.org76b82082010-03-24 17:59:39 +0000155 case EOpPostIncrement: out.debug << "Post-Increment"; break;
156 case EOpPostDecrement: out.debug << "Post-Decrement"; break;
157 case EOpPreIncrement: out.debug << "Pre-Increment"; break;
158 case EOpPreDecrement: out.debug << "Pre-Decrement"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159
alokp@chromium.org76b82082010-03-24 17:59:39 +0000160 case EOpConvIntToBool: out.debug << "Convert int to bool"; break;
161 case EOpConvFloatToBool:out.debug << "Convert float to bool";break;
162 case EOpConvBoolToFloat:out.debug << "Convert bool to float";break;
163 case EOpConvIntToFloat: out.debug << "Convert int to float"; break;
164 case EOpConvFloatToInt: out.debug << "Convert float to int"; break;
165 case EOpConvBoolToInt: out.debug << "Convert bool to int"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166
alokp@chromium.org76b82082010-03-24 17:59:39 +0000167 case EOpRadians: out.debug << "radians"; break;
168 case EOpDegrees: out.debug << "degrees"; break;
169 case EOpSin: out.debug << "sine"; break;
170 case EOpCos: out.debug << "cosine"; break;
171 case EOpTan: out.debug << "tangent"; break;
172 case EOpAsin: out.debug << "arc sine"; break;
173 case EOpAcos: out.debug << "arc cosine"; break;
174 case EOpAtan: out.debug << "arc tangent"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
alokp@chromium.org76b82082010-03-24 17:59:39 +0000176 case EOpExp: out.debug << "exp"; break;
177 case EOpLog: out.debug << "log"; break;
178 case EOpExp2: out.debug << "exp2"; break;
179 case EOpLog2: out.debug << "log2"; break;
180 case EOpSqrt: out.debug << "sqrt"; break;
181 case EOpInverseSqrt: out.debug << "inverse sqrt"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182
alokp@chromium.org76b82082010-03-24 17:59:39 +0000183 case EOpAbs: out.debug << "Absolute value"; break;
184 case EOpSign: out.debug << "Sign"; break;
185 case EOpFloor: out.debug << "Floor"; break;
186 case EOpCeil: out.debug << "Ceiling"; break;
187 case EOpFract: out.debug << "Fraction"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188
alokp@chromium.org76b82082010-03-24 17:59:39 +0000189 case EOpLength: out.debug << "length"; break;
190 case EOpNormalize: out.debug << "normalize"; break;
191 // case EOpDPdx: out.debug << "dPdx"; break;
192 // case EOpDPdy: out.debug << "dPdy"; break;
193 // case EOpFwidth: out.debug << "fwidth"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194
alokp@chromium.org76b82082010-03-24 17:59:39 +0000195 case EOpAny: out.debug << "any"; break;
196 case EOpAll: out.debug << "all"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197
alokp@chromium.org76b82082010-03-24 17:59:39 +0000198 default: out.debug.message(EPrefixError, "Bad unary op");
199 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200
alokp@chromium.org76b82082010-03-24 17:59:39 +0000201 out.debug << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
alokp@chromium.org76b82082010-03-24 17:59:39 +0000203 out.debug << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
alokp@chromium.org76b82082010-03-24 17:59:39 +0000205 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206}
207
208bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
209{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000210 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211
alokp@chromium.org76b82082010-03-24 17:59:39 +0000212 if (node->getOp() == EOpNull) {
213 out.debug.message(EPrefixError, "node is still EOpNull!");
214 return true;
215 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216
alokp@chromium.org76b82082010-03-24 17:59:39 +0000217 OutputTreeText(out, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218
alokp@chromium.org76b82082010-03-24 17:59:39 +0000219 switch (node->getOp()) {
220 case EOpSequence: out.debug << "Sequence\n"; return true;
221 case EOpComma: out.debug << "Comma\n"; return true;
222 case EOpFunction: out.debug << "Function Definition: " << node->getName(); break;
223 case EOpFunctionCall: out.debug << "Function Call: " << node->getName(); break;
224 case EOpParameters: out.debug << "Function Parameters: "; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225
alokp@chromium.org76b82082010-03-24 17:59:39 +0000226 case EOpConstructFloat: out.debug << "Construct float"; break;
227 case EOpConstructVec2: out.debug << "Construct vec2"; break;
228 case EOpConstructVec3: out.debug << "Construct vec3"; break;
229 case EOpConstructVec4: out.debug << "Construct vec4"; break;
230 case EOpConstructBool: out.debug << "Construct bool"; break;
231 case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
232 case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
233 case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
234 case EOpConstructInt: out.debug << "Construct int"; break;
235 case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
236 case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
237 case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
238 case EOpConstructMat2: out.debug << "Construct mat2"; break;
239 case EOpConstructMat3: out.debug << "Construct mat3"; break;
240 case EOpConstructMat4: out.debug << "Construct mat4"; break;
241 case EOpConstructStruct: out.debug << "Construct structure"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242
alokp@chromium.org76b82082010-03-24 17:59:39 +0000243 case EOpLessThan: out.debug << "Compare Less Than"; break;
244 case EOpGreaterThan: out.debug << "Compare Greater Than"; break;
245 case EOpLessThanEqual: out.debug << "Compare Less Than or Equal"; break;
246 case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
247 case EOpVectorEqual: out.debug << "Equal"; break;
248 case EOpVectorNotEqual: out.debug << "NotEqual"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
alokp@chromium.org76b82082010-03-24 17:59:39 +0000250 case EOpMod: out.debug << "mod"; break;
251 case EOpPow: out.debug << "pow"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252
alokp@chromium.org76b82082010-03-24 17:59:39 +0000253 case EOpAtan: out.debug << "arc tangent"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254
alokp@chromium.org76b82082010-03-24 17:59:39 +0000255 case EOpMin: out.debug << "min"; break;
256 case EOpMax: out.debug << "max"; break;
257 case EOpClamp: out.debug << "clamp"; break;
258 case EOpMix: out.debug << "mix"; break;
259 case EOpStep: out.debug << "step"; break;
260 case EOpSmoothStep: out.debug << "smoothstep"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261
alokp@chromium.org76b82082010-03-24 17:59:39 +0000262 case EOpDistance: out.debug << "distance"; break;
263 case EOpDot: out.debug << "dot-product"; break;
264 case EOpCross: out.debug << "cross-product"; break;
265 case EOpFaceForward: out.debug << "face-forward"; break;
266 case EOpReflect: out.debug << "reflect"; break;
267 case EOpRefract: out.debug << "refract"; break;
268 case EOpMul: out.debug << "component-wise multiply"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269
alokp@chromium.org76b82082010-03-24 17:59:39 +0000270 default: out.debug.message(EPrefixError, "Bad aggregation op");
271 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272
alokp@chromium.org76b82082010-03-24 17:59:39 +0000273 if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
274 out.debug << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275
alokp@chromium.org76b82082010-03-24 17:59:39 +0000276 out.debug << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
alokp@chromium.org76b82082010-03-24 17:59:39 +0000278 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279}
280
281bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
282{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000283 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284
alokp@chromium.org76b82082010-03-24 17:59:39 +0000285 OutputTreeText(out, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286
alokp@chromium.org76b82082010-03-24 17:59:39 +0000287 out.debug << "Test condition and select";
288 out.debug << " (" << node->getCompleteString() << ")\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289
alokp@chromium.org76b82082010-03-24 17:59:39 +0000290 ++depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291
alokp@chromium.org76b82082010-03-24 17:59:39 +0000292 OutputTreeText(infoSink, node, depth);
293 out.debug << "Condition\n";
294 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295
alokp@chromium.org76b82082010-03-24 17:59:39 +0000296 OutputTreeText(infoSink, node, depth);
297 if (node->getTrueBlock()) {
298 out.debug << "true case\n";
299 node->getTrueBlock()->traverse(this);
300 } else
301 out.debug << "true case is null\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
alokp@chromium.org76b82082010-03-24 17:59:39 +0000303 if (node->getFalseBlock()) {
304 OutputTreeText(infoSink, node, depth);
305 out.debug << "false case\n";
306 node->getFalseBlock()->traverse(this);
307 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308
alokp@chromium.org76b82082010-03-24 17:59:39 +0000309 --depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
alokp@chromium.org76b82082010-03-24 17:59:39 +0000311 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312}
313
314void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
315{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000316 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317
alokp@chromium.org76b82082010-03-24 17:59:39 +0000318 int size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319
alokp@chromium.org76b82082010-03-24 17:59:39 +0000320 char buf[300];
321 for (int i = 0; i < size; i++) {
322 OutputTreeText(out, node, depth);
323 switch (node->getUnionArrayPointer()[i].getType()) {
324 case EbtBool:
325 if (node->getUnionArrayPointer()[i].getBConst())
326 out.debug << "true";
327 else
328 out.debug << "false";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329
alokp@chromium.org76b82082010-03-24 17:59:39 +0000330 out.debug << " (" << "const bool" << ")";
331 out.debug << "\n";
332 break;
333 case EbtFloat:
334 sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float");
335 out.debug << buf << "\n";
336 break;
337 case EbtInt:
338 sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].getIConst(), "const int");
339 out.debug << buf << "\n";
340 break;
341 default:
342 out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
343 break;
344 }
345 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346}
347
348bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
349{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000350 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351
alokp@chromium.org76b82082010-03-24 17:59:39 +0000352 OutputTreeText(out, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353
alokp@chromium.org76b82082010-03-24 17:59:39 +0000354 out.debug << "Loop with condition ";
355 if (! node->testFirst())
356 out.debug << "not ";
357 out.debug << "tested first\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358
alokp@chromium.org76b82082010-03-24 17:59:39 +0000359 ++depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360
alokp@chromium.org76b82082010-03-24 17:59:39 +0000361 OutputTreeText(infoSink, node, depth);
362 if (node->getTest()) {
363 out.debug << "Loop Condition\n";
364 node->getTest()->traverse(this);
365 } else
366 out.debug << "No loop condition\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367
alokp@chromium.org76b82082010-03-24 17:59:39 +0000368 OutputTreeText(infoSink, node, depth);
369 if (node->getBody()) {
370 out.debug << "Loop Body\n";
371 node->getBody()->traverse(this);
372 } else
373 out.debug << "No loop body\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374
alokp@chromium.org76b82082010-03-24 17:59:39 +0000375 if (node->getTerminal()) {
376 OutputTreeText(infoSink, node, depth);
377 out.debug << "Loop Terminal Expression\n";
378 node->getTerminal()->traverse(this);
379 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380
alokp@chromium.org76b82082010-03-24 17:59:39 +0000381 --depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382
alokp@chromium.org76b82082010-03-24 17:59:39 +0000383 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384}
385
386bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
387{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000388 TInfoSink& out = infoSink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000389
alokp@chromium.org76b82082010-03-24 17:59:39 +0000390 OutputTreeText(out, node, depth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391
alokp@chromium.org76b82082010-03-24 17:59:39 +0000392 switch (node->getFlowOp()) {
393 case EOpKill: out.debug << "Branch: Kill"; break;
394 case EOpBreak: out.debug << "Branch: Break"; break;
395 case EOpContinue: out.debug << "Branch: Continue"; break;
396 case EOpReturn: out.debug << "Branch: Return"; break;
397 default: out.debug << "Branch: Unknown Branch"; break;
398 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399
alokp@chromium.org76b82082010-03-24 17:59:39 +0000400 if (node->getExpression()) {
401 out.debug << " with expression\n";
402 ++depth;
403 node->getExpression()->traverse(this);
404 --depth;
405 } else
406 out.debug << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407
alokp@chromium.org76b82082010-03-24 17:59:39 +0000408 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409}
410
411//
412// This function is the one to call externally to start the traversal.
413// Individual functions can be initialized to 0 to skip processing of that
414// type of node. It's children will still be processed.
415//
416void TIntermediate::outputTree(TIntermNode* root)
417{
alokp@chromium.org76b82082010-03-24 17:59:39 +0000418 if (root == 0)
419 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000420
alokp@chromium.org76b82082010-03-24 17:59:39 +0000421 TOutputTraverser it(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000422
alokp@chromium.org76b82082010-03-24 17:59:39 +0000423 root->traverse(&it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000424}