blob: 352fde35a531cd3ea56ba5e8fd7d84904eda5484 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens16004fc2014-06-11 11:29:11 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Jamie Madillb1a85f42014-08-19 15:23:24 -04007#include "compiler/translator/Intermediate.h"
Geoff Lang17732822013-08-29 13:46:49 -04008#include "compiler/translator/SymbolTable.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009
Zhenyao Moe40d1e92014-07-16 17:40:36 -070010namespace
11{
12
Olli Etuaho336b1472016-10-05 16:37:55 +010013void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info)
Olli Etuaho5f579b12015-08-14 17:44:43 +030014{
Olli Etuaho336b1472016-10-05 16:37:55 +010015 const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
16 out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
17 << info->getId() << ")";
Olli Etuaho5f579b12015-08-14 17:44:43 +030018}
19
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000020//
21// Two purposes:
22// 1. Show an example of how to iterate tree. Functions can
23// also directly call Traverse() on children themselves to
24// have finer grained control over the process than shown here.
25// See the last function for how to get started.
26// 2. Print out a text based description of the tree.
27//
28
29//
30// Use this class to carry along data from node to node in
31// the traversal
32//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070033class TOutputTraverser : public TIntermTraverser
34{
35 public:
36 TOutputTraverser(TInfoSinkBase &i)
Olli Etuaho3d0d9a42015-06-01 12:16:36 +030037 : TIntermTraverser(true, false, false),
38 sink(i)
39 {
40 }
alokp@chromium.org7beea402010-09-15 21:18:34 +000041 TInfoSinkBase& sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042
Zhenyao Moe40d1e92014-07-16 17:40:36 -070043 protected:
Corentin Walleze5a1f272015-08-21 02:58:25 +020044 void visitSymbol(TIntermSymbol *) override;
45 void visitConstantUnion(TIntermConstantUnion *) override;
Olli Etuahob6fa0432016-09-28 16:28:05 +010046 bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020047 bool visitBinary(Visit visit, TIntermBinary *) override;
48 bool visitUnary(Visit visit, TIntermUnary *) override;
Olli Etuahod0bad2c2016-09-09 18:01:16 +030049 bool visitTernary(Visit visit, TIntermTernary *node) override;
Olli Etuaho57961272016-09-14 13:57:46 +030050 bool visitIfElse(Visit visit, TIntermIfElse *node) override;
Olli Etuaho13e4d212016-10-13 11:50:27 +010051 bool visitSwitch(Visit visit, TIntermSwitch *node) override;
52 bool visitCase(Visit visit, TIntermCase *node) override;
Olli Etuaho336b1472016-10-05 16:37:55 +010053 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020054 bool visitAggregate(Visit visit, TIntermAggregate *) override;
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010055 bool visitBlock(Visit visit, TIntermBlock *) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020056 bool visitLoop(Visit visit, TIntermLoop *) override;
57 bool visitBranch(Visit visit, TIntermBranch *) override;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058};
59
Zhenyao Moe40d1e92014-07-16 17:40:36 -070060//
61// Helper functions for printing, not part of traversing.
62//
63void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
64{
65 int i;
66
67 sink.location(node->getLine());
68
69 for (i = 0; i < depth; ++i)
70 sink << " ";
71}
72
73} // namespace anonymous
74
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000076// The rest of the file are the traversal functions. The last one
77// is the one that starts the traversal.
78//
79// Return true from interior nodes to have the external traversal
80// continue on to children. If you process children yourself,
81// return false.
82//
83
Zhenyao Moe40d1e92014-07-16 17:40:36 -070084void TOutputTraverser::visitSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070086 OutputTreeText(sink, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087
alokp@chromium.org7beea402010-09-15 21:18:34 +000088 sink << "'" << node->getSymbol() << "' ";
89 sink << "(" << node->getCompleteString() << ")\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090}
91
Olli Etuahob6fa0432016-09-28 16:28:05 +010092bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
93{
94 TInfoSinkBase &out = sink;
95 OutputTreeText(out, node, mDepth);
96 out << "vector swizzle";
97 return true;
98}
99
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700100bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000102 TInfoSinkBase& out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700104 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700106 switch (node->getOp())
107 {
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100108 case EOpComma:
109 out << "comma";
110 break;
111 case EOpAssign:
112 out << "move second child to first child";
113 break;
114 case EOpInitialize:
115 out << "initialize first child with second child";
116 break;
117 case EOpAddAssign:
118 out << "add second child into first child";
119 break;
120 case EOpSubAssign:
121 out << "subtract second child into first child";
122 break;
123 case EOpMulAssign:
124 out << "multiply second child into first child";
125 break;
126 case EOpVectorTimesMatrixAssign:
127 out << "matrix mult second child into first child";
128 break;
129 case EOpVectorTimesScalarAssign:
130 out << "vector scale second child into first child";
131 break;
132 case EOpMatrixTimesScalarAssign:
133 out << "matrix scale second child into first child";
134 break;
135 case EOpMatrixTimesMatrixAssign:
136 out << "matrix mult second child into first child";
137 break;
138 case EOpDivAssign:
139 out << "divide second child into first child";
140 break;
141 case EOpIModAssign:
142 out << "modulo second child into first child";
143 break;
144 case EOpBitShiftLeftAssign:
145 out << "bit-wise shift first child left by second child";
146 break;
147 case EOpBitShiftRightAssign:
148 out << "bit-wise shift first child right by second child";
149 break;
150 case EOpBitwiseAndAssign:
151 out << "bit-wise and second child into first child";
152 break;
153 case EOpBitwiseXorAssign:
154 out << "bit-wise xor second child into first child";
155 break;
156 case EOpBitwiseOrAssign:
157 out << "bit-wise or second child into first child";
158 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200159
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100160 case EOpIndexDirect:
161 out << "direct index";
162 break;
163 case EOpIndexIndirect:
164 out << "indirect index";
165 break;
166 case EOpIndexDirectStruct:
167 out << "direct index for structure";
168 break;
169 case EOpIndexDirectInterfaceBlock:
170 out << "direct index for interface block";
171 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100173 case EOpAdd:
174 out << "add";
175 break;
176 case EOpSub:
177 out << "subtract";
178 break;
179 case EOpMul:
180 out << "component-wise multiply";
181 break;
182 case EOpDiv:
183 out << "divide";
184 break;
185 case EOpIMod:
186 out << "modulo";
187 break;
188 case EOpBitShiftLeft:
189 out << "bit-wise shift left";
190 break;
191 case EOpBitShiftRight:
192 out << "bit-wise shift right";
193 break;
194 case EOpBitwiseAnd:
195 out << "bit-wise and";
196 break;
197 case EOpBitwiseXor:
198 out << "bit-wise xor";
199 break;
200 case EOpBitwiseOr:
201 out << "bit-wise or";
202 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200203
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100204 case EOpEqual:
205 out << "Compare Equal";
206 break;
207 case EOpNotEqual:
208 out << "Compare Not Equal";
209 break;
210 case EOpLessThan:
211 out << "Compare Less Than";
212 break;
213 case EOpGreaterThan:
214 out << "Compare Greater Than";
215 break;
216 case EOpLessThanEqual:
217 out << "Compare Less Than or Equal";
218 break;
219 case EOpGreaterThanEqual:
220 out << "Compare Greater Than or Equal";
221 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100223 case EOpVectorTimesScalar:
224 out << "vector-scale";
225 break;
226 case EOpVectorTimesMatrix:
227 out << "vector-times-matrix";
228 break;
229 case EOpMatrixTimesVector:
230 out << "matrix-times-vector";
231 break;
232 case EOpMatrixTimesScalar:
233 out << "matrix-scale";
234 break;
235 case EOpMatrixTimesMatrix:
236 out << "matrix-multiply";
237 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100239 case EOpLogicalOr:
240 out << "logical-or";
241 break;
242 case EOpLogicalXor:
243 out << "logical-xor";
244 break;
245 case EOpLogicalAnd:
246 out << "logical-and";
247 break;
248 default:
249 out << "<unknown op>";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000250 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251
alokp@chromium.org7beea402010-09-15 21:18:34 +0000252 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253
alokp@chromium.org7beea402010-09-15 21:18:34 +0000254 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
Jamie Madill60305f12014-11-18 13:25:26 -0500256 // Special handling for direct indexes. Because constant
257 // unions are not aware they are struct indexes, treat them
258 // here where we have that contextual knowledge.
259 if (node->getOp() == EOpIndexDirectStruct ||
260 node->getOp() == EOpIndexDirectInterfaceBlock)
261 {
262 mDepth++;
263 node->getLeft()->traverse(this);
264 mDepth--;
265
266 TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
267 ASSERT(intermConstantUnion);
268
269 OutputTreeText(out, intermConstantUnion, mDepth + 1);
270
271 // The following code finds the field name from the constant union
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400272 const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
Jamie Madill60305f12014-11-18 13:25:26 -0500273 const TStructure *structure = node->getLeft()->getType().getStruct();
274 const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
275 ASSERT(structure || interfaceBlock);
276
277 const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
278
279 const TField *field = fields[constantUnion->getIConst()];
280
281 out << constantUnion->getIConst() << " (field '" << field->name() << "')";
282
283 return false;
284 }
285
alokp@chromium.org76b82082010-03-24 17:59:39 +0000286 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287}
288
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700289bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000291 TInfoSinkBase& out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700293 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700295 switch (node->getOp())
296 {
297 case EOpNegative: out << "Negate value"; break;
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700298 case EOpPositive: out << "Positive sign"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700299 case EOpVectorLogicalNot:
300 case EOpLogicalNot: out << "Negate conditional"; break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200301 case EOpBitwiseNot: out << "bit-wise not"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700303 case EOpPostIncrement: out << "Post-Increment"; break;
304 case EOpPostDecrement: out << "Post-Decrement"; break;
305 case EOpPreIncrement: out << "Pre-Increment"; break;
306 case EOpPreDecrement: out << "Pre-Decrement"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700308 case EOpRadians: out << "radians"; break;
309 case EOpDegrees: out << "degrees"; break;
310 case EOpSin: out << "sine"; break;
311 case EOpCos: out << "cosine"; break;
312 case EOpTan: out << "tangent"; break;
313 case EOpAsin: out << "arc sine"; break;
314 case EOpAcos: out << "arc cosine"; break;
315 case EOpAtan: out << "arc tangent"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316
Olli Etuaho5c9cd3d2014-12-18 13:04:25 +0200317 case EOpSinh: out << "hyperbolic sine"; break;
318 case EOpCosh: out << "hyperbolic cosine"; break;
319 case EOpTanh: out << "hyperbolic tangent"; break;
320 case EOpAsinh: out << "arc hyperbolic sine"; break;
321 case EOpAcosh: out << "arc hyperbolic cosine"; break;
322 case EOpAtanh: out << "arc hyperbolic tangent"; break;
323
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700324 case EOpExp: out << "exp"; break;
325 case EOpLog: out << "log"; break;
326 case EOpExp2: out << "exp2"; break;
327 case EOpLog2: out << "log2"; break;
328 case EOpSqrt: out << "sqrt"; break;
329 case EOpInverseSqrt: out << "inverse sqrt"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700331 case EOpAbs: out << "Absolute value"; break;
332 case EOpSign: out << "Sign"; break;
333 case EOpFloor: out << "Floor"; break;
Qingqing Deng5dbece52015-02-27 20:35:38 -0800334 case EOpTrunc: out << "Truncate"; break;
335 case EOpRound: out << "Round"; break;
336 case EOpRoundEven: out << "Round half even"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700337 case EOpCeil: out << "Ceiling"; break;
338 case EOpFract: out << "Fraction"; break;
Arun Patole0c1726e2015-02-18 14:35:02 +0530339 case EOpIsNan: out << "Is not a number"; break;
340 case EOpIsInf: out << "Is infinity"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341
Olli Etuahoe8d2c072015-01-08 16:33:54 +0200342 case EOpFloatBitsToInt: out << "float bits to int"; break;
343 case EOpFloatBitsToUint: out << "float bits to uint"; break;
344 case EOpIntBitsToFloat: out << "int bits to float"; break;
345 case EOpUintBitsToFloat: out << "uint bits to float"; break;
346
Olli Etuaho7700ff62015-01-15 12:16:29 +0200347 case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break;
348 case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break;
349 case EOpPackHalf2x16: out << "pack half 2x16"; break;
350
351 case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break;
352 case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break;
353 case EOpUnpackHalf2x16: out << "unpack half 2x16"; break;
354
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700355 case EOpLength: out << "length"; break;
356 case EOpNormalize: out << "normalize"; break;
357 // case EOpDPdx: out << "dPdx"; break;
358 // case EOpDPdy: out << "dPdy"; break;
359 // case EOpFwidth: out << "fwidth"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360
Olli Etuahoe39706d2014-12-30 16:40:36 +0200361 case EOpDeterminant: out << "determinant"; break;
362 case EOpTranspose: out << "transpose"; break;
Olli Etuahoabf6dad2015-01-14 14:45:16 +0200363 case EOpInverse: out << "inverse"; break;
Olli Etuahoe39706d2014-12-30 16:40:36 +0200364
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700365 case EOpAny: out << "any"; break;
366 case EOpAll: out << "all"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700368 default:
369 out.prefix(EPrefixError);
370 out << "Bad unary op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000371 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372
alokp@chromium.org7beea402010-09-15 21:18:34 +0000373 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374
alokp@chromium.org7beea402010-09-15 21:18:34 +0000375 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376
alokp@chromium.org76b82082010-03-24 17:59:39 +0000377 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378}
379
Olli Etuaho336b1472016-10-05 16:37:55 +0100380bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
381{
382 TInfoSinkBase &out = sink;
383 OutputTreeText(out, node, mDepth);
384 OutputFunction(out, "Function Definition", node->getFunctionSymbolInfo());
385 out << "\n";
386 return true;
387}
388
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700389bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700391 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100393 OutputTreeText(out, node, mDepth);
394
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700395 if (node->getOp() == EOpNull)
396 {
Jamie Madill075edd82013-07-08 13:30:19 -0400397 out.prefix(EPrefixError);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100398 out << "node is still EOpNull!\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000399 return true;
400 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000402
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700403 switch (node->getOp())
404 {
Olli Etuaho336b1472016-10-05 16:37:55 +0100405 case EOpFunctionCall:
406 OutputFunction(out, "Function Call", node->getFunctionSymbolInfo());
407 break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700408 case EOpParameters: out << "Function Parameters: "; break;
Olli Etuaho336b1472016-10-05 16:37:55 +0100409 case EOpPrototype:
410 OutputFunction(out, "Function Prototype", node->getFunctionSymbolInfo());
411 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700413 case EOpConstructFloat: out << "Construct float"; break;
414 case EOpConstructVec2: out << "Construct vec2"; break;
415 case EOpConstructVec3: out << "Construct vec3"; break;
416 case EOpConstructVec4: out << "Construct vec4"; break;
417 case EOpConstructBool: out << "Construct bool"; break;
418 case EOpConstructBVec2: out << "Construct bvec2"; break;
419 case EOpConstructBVec3: out << "Construct bvec3"; break;
420 case EOpConstructBVec4: out << "Construct bvec4"; break;
421 case EOpConstructInt: out << "Construct int"; break;
422 case EOpConstructIVec2: out << "Construct ivec2"; break;
423 case EOpConstructIVec3: out << "Construct ivec3"; break;
424 case EOpConstructIVec4: out << "Construct ivec4"; break;
425 case EOpConstructUInt: out << "Construct uint"; break;
426 case EOpConstructUVec2: out << "Construct uvec2"; break;
427 case EOpConstructUVec3: out << "Construct uvec3"; break;
428 case EOpConstructUVec4: out << "Construct uvec4"; break;
429 case EOpConstructMat2: out << "Construct mat2"; break;
Alexis Hetu07e57df2015-06-16 16:55:52 -0400430 case EOpConstructMat2x3: out << "Construct mat2x3"; break;
431 case EOpConstructMat2x4: out << "Construct mat2x4"; break;
432 case EOpConstructMat3x2: out << "Construct mat3x2"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700433 case EOpConstructMat3: out << "Construct mat3"; break;
Alexis Hetu07e57df2015-06-16 16:55:52 -0400434 case EOpConstructMat3x4: out << "Construct mat3x4"; break;
435 case EOpConstructMat4x2: out << "Construct mat4x2"; break;
436 case EOpConstructMat4x3: out << "Construct mat4x3"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700437 case EOpConstructMat4: out << "Construct mat4"; break;
438 case EOpConstructStruct: out << "Construct structure"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000439
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700440 case EOpLessThan: out << "Compare Less Than"; break;
441 case EOpGreaterThan: out << "Compare Greater Than"; break;
442 case EOpLessThanEqual: out << "Compare Less Than or Equal"; break;
443 case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
444 case EOpVectorEqual: out << "Equal"; break;
445 case EOpVectorNotEqual: out << "NotEqual"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700447 case EOpMod: out << "mod"; break;
Olli Etuahob6e07a62015-02-16 12:22:10 +0200448 case EOpModf: out << "modf"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700449 case EOpPow: out << "pow"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000450
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700451 case EOpAtan: out << "arc tangent"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000452
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700453 case EOpMin: out << "min"; break;
454 case EOpMax: out << "max"; break;
455 case EOpClamp: out << "clamp"; break;
456 case EOpMix: out << "mix"; break;
457 case EOpStep: out << "step"; break;
458 case EOpSmoothStep: out << "smoothstep"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000459
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700460 case EOpDistance: out << "distance"; break;
461 case EOpDot: out << "dot-product"; break;
462 case EOpCross: out << "cross-product"; break;
463 case EOpFaceForward: out << "face-forward"; break;
464 case EOpReflect: out << "reflect"; break;
465 case EOpRefract: out << "refract"; break;
466 case EOpMul: out << "component-wise multiply"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000467
Olli Etuahoe39706d2014-12-30 16:40:36 +0200468 case EOpOuterProduct: out << "outer product"; break;
469
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700470 case EOpDeclaration: out << "Declaration: "; break;
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400471 case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
daniel@transgaming.coma9ae4aa2011-10-19 13:29:27 +0000472
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700473 default:
474 out.prefix(EPrefixError);
475 out << "Bad aggregation op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000476 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000477
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100478 if (node->getOp() != EOpParameters)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000479 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000480
alokp@chromium.org7beea402010-09-15 21:18:34 +0000481 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482
alokp@chromium.org76b82082010-03-24 17:59:39 +0000483 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484}
485
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100486bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
487{
488 TInfoSinkBase &out = sink;
489
490 OutputTreeText(out, node, mDepth);
491 out << "Code block\n";
492
493 return true;
494}
495
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300496bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
497{
498 TInfoSinkBase &out = sink;
499
500 OutputTreeText(out, node, mDepth);
501
502 out << "Ternary selection";
503 out << " (" << node->getCompleteString() << ")\n";
504
505 ++mDepth;
506
507 OutputTreeText(sink, node, mDepth);
508 out << "Condition\n";
509 node->getCondition()->traverse(this);
510
511 OutputTreeText(sink, node, mDepth);
512 if (node->getTrueExpression())
513 {
514 out << "true case\n";
515 node->getTrueExpression()->traverse(this);
516 }
517 if (node->getFalseExpression())
518 {
519 OutputTreeText(sink, node, mDepth);
520 out << "false case\n";
521 node->getFalseExpression()->traverse(this);
522 }
523
524 --mDepth;
525
526 return false;
527}
528
Olli Etuaho57961272016-09-14 13:57:46 +0300529bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000530{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700531 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700533 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300535 out << "If test\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700537 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700539 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000540 out << "Condition\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000541 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700543 OutputTreeText(sink, node, mDepth);
544 if (node->getTrueBlock())
545 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000546 out << "true case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000547 node->getTrueBlock()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700548 }
549 else
550 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000551 out << "true case is null\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700552 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000553
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700554 if (node->getFalseBlock())
555 {
556 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000557 out << "false case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000558 node->getFalseBlock()->traverse(this);
559 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000560
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700561 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000562
alokp@chromium.org76b82082010-03-24 17:59:39 +0000563 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000564}
565
Olli Etuaho13e4d212016-10-13 11:50:27 +0100566bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
567{
568 TInfoSinkBase &out = sink;
569
570 OutputTreeText(out, node, mDepth);
571
572 out << "Switch\n";
573
574 return true;
575}
576
577bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
578{
579 TInfoSinkBase &out = sink;
580
581 OutputTreeText(out, node, mDepth);
582
583 if (node->getCondition() == nullptr)
584 {
585 out << "Default\n";
586 }
587 else
588 {
589 out << "Case\n";
590 }
591
592 return true;
593}
594
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700595void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700597 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598
Jamie Madill94bf7f22013-07-08 13:31:15 -0400599 size_t size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700601 for (size_t i = 0; i < size; i++)
602 {
603 OutputTreeText(out, node, mDepth);
604 switch (node->getUnionArrayPointer()[i].getType())
605 {
606 case EbtBool:
607 if (node->getUnionArrayPointer()[i].getBConst())
608 out << "true";
609 else
610 out << "false";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000611
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700612 out << " (" << "const bool" << ")";
613 out << "\n";
614 break;
615 case EbtFloat:
616 out << node->getUnionArrayPointer()[i].getFConst();
617 out << " (const float)\n";
618 break;
619 case EbtInt:
620 out << node->getUnionArrayPointer()[i].getIConst();
621 out << " (const int)\n";
622 break;
623 case EbtUInt:
624 out << node->getUnionArrayPointer()[i].getUConst();
625 out << " (const uint)\n";
626 break;
627 default:
628 out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
629 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000630 }
631 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000632}
633
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700634bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700636 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700638 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000639
alokp@chromium.org7beea402010-09-15 21:18:34 +0000640 out << "Loop with condition ";
alokp@chromium.org52813552010-11-16 18:36:09 +0000641 if (node->getType() == ELoopDoWhile)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000642 out << "not ";
643 out << "tested first\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700645 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000646
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700647 OutputTreeText(sink, node, mDepth);
648 if (node->getCondition())
649 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000650 out << "Loop Condition\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000651 node->getCondition()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700652 }
653 else
654 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000655 out << "No loop condition\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700656 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700658 OutputTreeText(sink, node, mDepth);
659 if (node->getBody())
660 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000661 out << "Loop Body\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000662 node->getBody()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700663 }
664 else
665 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000666 out << "No loop body\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700667 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700669 if (node->getExpression())
670 {
671 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000672 out << "Loop Terminal Expression\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000673 node->getExpression()->traverse(this);
alokp@chromium.org76b82082010-03-24 17:59:39 +0000674 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700676 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000677
alokp@chromium.org76b82082010-03-24 17:59:39 +0000678 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000679}
680
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700681bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000682{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700683 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700685 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000686
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700687 switch (node->getFlowOp())
688 {
689 case EOpKill: out << "Branch: Kill"; break;
690 case EOpBreak: out << "Branch: Break"; break;
691 case EOpContinue: out << "Branch: Continue"; break;
692 case EOpReturn: out << "Branch: Return"; break;
693 default: out << "Branch: Unknown Branch"; break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000694 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000695
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700696 if (node->getExpression())
697 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000698 out << " with expression\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700699 ++mDepth;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000700 node->getExpression()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700701 --mDepth;
702 }
703 else
704 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000705 out << "\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700706 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000707
alokp@chromium.org76b82082010-03-24 17:59:39 +0000708 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000709}
710
711//
712// This function is the one to call externally to start the traversal.
713// Individual functions can be initialized to 0 to skip processing of that
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200714// type of node. Its children will still be processed.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000715//
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200716void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200718 TOutputTraverser it(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000719
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200720 ASSERT(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721
alokp@chromium.org76b82082010-03-24 17:59:39 +0000722 root->traverse(&it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723}