blob: 42e29c8cbf68483600a52223f8262d01a275cfba [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 Etuaho336b1472016-10-05 16:37:55 +010051 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020052 bool visitAggregate(Visit visit, TIntermAggregate *) override;
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010053 bool visitBlock(Visit visit, TIntermBlock *) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020054 bool visitLoop(Visit visit, TIntermLoop *) override;
55 bool visitBranch(Visit visit, TIntermBranch *) override;
Olli Etuahod0bad2c2016-09-09 18:01:16 +030056 // TODO: Add missing visit functions
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057};
58
Zhenyao Moe40d1e92014-07-16 17:40:36 -070059//
60// Helper functions for printing, not part of traversing.
61//
62void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
63{
64 int i;
65
66 sink.location(node->getLine());
67
68 for (i = 0; i < depth; ++i)
69 sink << " ";
70}
71
72} // namespace anonymous
73
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000074//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075// The rest of the file are the traversal functions. The last one
76// is the one that starts the traversal.
77//
78// Return true from interior nodes to have the external traversal
79// continue on to children. If you process children yourself,
80// return false.
81//
82
Zhenyao Moe40d1e92014-07-16 17:40:36 -070083void TOutputTraverser::visitSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070085 OutputTreeText(sink, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
alokp@chromium.org7beea402010-09-15 21:18:34 +000087 sink << "'" << node->getSymbol() << "' ";
88 sink << "(" << node->getCompleteString() << ")\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089}
90
Olli Etuahob6fa0432016-09-28 16:28:05 +010091bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
92{
93 TInfoSinkBase &out = sink;
94 OutputTreeText(out, node, mDepth);
95 out << "vector swizzle";
96 return true;
97}
98
Zhenyao Moe40d1e92014-07-16 17:40:36 -070099bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000101 TInfoSinkBase& out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700103 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700105 switch (node->getOp())
106 {
107 case EOpAssign:
108 out << "move second child to first child";
109 break;
110 case EOpInitialize:
111 out << "initialize first child with second child";
112 break;
113 case EOpAddAssign:
114 out << "add second child into first child";
115 break;
116 case EOpSubAssign:
117 out << "subtract second child into first child";
118 break;
119 case EOpMulAssign:
120 out << "multiply second child into first child";
121 break;
122 case EOpVectorTimesMatrixAssign:
123 out << "matrix mult second child into first child";
124 break;
125 case EOpVectorTimesScalarAssign:
126 out << "vector scale second child into first child";
127 break;
128 case EOpMatrixTimesScalarAssign:
129 out << "matrix scale second child into first child";
130 break;
131 case EOpMatrixTimesMatrixAssign:
132 out << "matrix mult second child into first child";
133 break;
134 case EOpDivAssign:
135 out << "divide second child into first child";
136 break;
Olli Etuahoff805cc2015-02-13 10:59:34 +0200137 case EOpIModAssign:
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +0000138 out << "modulo second child into first child";
139 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200140 case EOpBitShiftLeftAssign:
141 out << "bit-wise shift first child left by second child";
142 break;
143 case EOpBitShiftRightAssign:
144 out << "bit-wise shift first child right by second child";
145 break;
146 case EOpBitwiseAndAssign:
147 out << "bit-wise and second child into first child";
148 break;
149 case EOpBitwiseXorAssign:
150 out << "bit-wise xor second child into first child";
151 break;
152 case EOpBitwiseOrAssign:
153 out << "bit-wise or second child into first child";
154 break;
155
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700156 case EOpIndexDirect:
157 out << "direct index";
158 break;
159 case EOpIndexIndirect:
160 out << "indirect index";
161 break;
162 case EOpIndexDirectStruct:
163 out << "direct index for structure";
164 break;
165 case EOpIndexDirectInterfaceBlock:
166 out << "direct index for interface block";
167 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700169 case EOpAdd:
170 out << "add";
171 break;
172 case EOpSub:
173 out << "subtract";
174 break;
175 case EOpMul:
176 out << "component-wise multiply";
177 break;
178 case EOpDiv:
179 out << "divide";
180 break;
Olli Etuahoff805cc2015-02-13 10:59:34 +0200181 case EOpIMod:
Gregoire Payen de La Garanderiebe954a22014-12-23 00:05:28 +0000182 out << "modulo";
183 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200184 case EOpBitShiftLeft:
185 out << "bit-wise shift left";
186 break;
187 case EOpBitShiftRight:
188 out << "bit-wise shift right";
189 break;
190 case EOpBitwiseAnd:
191 out << "bit-wise and";
192 break;
193 case EOpBitwiseXor:
194 out << "bit-wise xor";
195 break;
196 case EOpBitwiseOr:
197 out << "bit-wise or";
198 break;
199
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700200 case EOpEqual:
201 out << "Compare Equal";
202 break;
203 case EOpNotEqual:
204 out << "Compare Not Equal";
205 break;
206 case EOpLessThan:
207 out << "Compare Less Than";
208 break;
209 case EOpGreaterThan:
210 out << "Compare Greater Than";
211 break;
212 case EOpLessThanEqual:
213 out << "Compare Less Than or Equal";
214 break;
215 case EOpGreaterThanEqual:
216 out << "Compare Greater Than or Equal";
217 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700219 case EOpVectorTimesScalar:
220 out << "vector-scale";
221 break;
222 case EOpVectorTimesMatrix:
223 out << "vector-times-matrix";
224 break;
225 case EOpMatrixTimesVector:
226 out << "matrix-times-vector";
227 break;
228 case EOpMatrixTimesScalar:
229 out << "matrix-scale";
230 break;
231 case EOpMatrixTimesMatrix:
232 out << "matrix-multiply";
233 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700235 case EOpLogicalOr:
236 out << "logical-or";
237 break;
238 case EOpLogicalXor:
239 out << "logical-xor";
240 break;
241 case EOpLogicalAnd:
242 out << "logical-and";
243 break;
244 default:
245 out << "<unknown op>";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000246 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247
alokp@chromium.org7beea402010-09-15 21:18:34 +0000248 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
alokp@chromium.org7beea402010-09-15 21:18:34 +0000250 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251
Jamie Madill60305f12014-11-18 13:25:26 -0500252 // Special handling for direct indexes. Because constant
253 // unions are not aware they are struct indexes, treat them
254 // here where we have that contextual knowledge.
255 if (node->getOp() == EOpIndexDirectStruct ||
256 node->getOp() == EOpIndexDirectInterfaceBlock)
257 {
258 mDepth++;
259 node->getLeft()->traverse(this);
260 mDepth--;
261
262 TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
263 ASSERT(intermConstantUnion);
264
265 OutputTreeText(out, intermConstantUnion, mDepth + 1);
266
267 // The following code finds the field name from the constant union
Jamie Madill6ba6ead2015-05-04 14:21:21 -0400268 const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
Jamie Madill60305f12014-11-18 13:25:26 -0500269 const TStructure *structure = node->getLeft()->getType().getStruct();
270 const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
271 ASSERT(structure || interfaceBlock);
272
273 const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
274
275 const TField *field = fields[constantUnion->getIConst()];
276
277 out << constantUnion->getIConst() << " (field '" << field->name() << "')";
278
279 return false;
280 }
281
alokp@chromium.org76b82082010-03-24 17:59:39 +0000282 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283}
284
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700285bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286{
alokp@chromium.org7beea402010-09-15 21:18:34 +0000287 TInfoSinkBase& out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700289 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700291 switch (node->getOp())
292 {
293 case EOpNegative: out << "Negate value"; break;
Zhenyao Mode1e00e2014-10-09 16:55:32 -0700294 case EOpPositive: out << "Positive sign"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700295 case EOpVectorLogicalNot:
296 case EOpLogicalNot: out << "Negate conditional"; break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200297 case EOpBitwiseNot: out << "bit-wise not"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700299 case EOpPostIncrement: out << "Post-Increment"; break;
300 case EOpPostDecrement: out << "Post-Decrement"; break;
301 case EOpPreIncrement: out << "Pre-Increment"; break;
302 case EOpPreDecrement: out << "Pre-Decrement"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 case EOpRadians: out << "radians"; break;
305 case EOpDegrees: out << "degrees"; break;
306 case EOpSin: out << "sine"; break;
307 case EOpCos: out << "cosine"; break;
308 case EOpTan: out << "tangent"; break;
309 case EOpAsin: out << "arc sine"; break;
310 case EOpAcos: out << "arc cosine"; break;
311 case EOpAtan: out << "arc tangent"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312
Olli Etuaho5c9cd3d2014-12-18 13:04:25 +0200313 case EOpSinh: out << "hyperbolic sine"; break;
314 case EOpCosh: out << "hyperbolic cosine"; break;
315 case EOpTanh: out << "hyperbolic tangent"; break;
316 case EOpAsinh: out << "arc hyperbolic sine"; break;
317 case EOpAcosh: out << "arc hyperbolic cosine"; break;
318 case EOpAtanh: out << "arc hyperbolic tangent"; break;
319
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700320 case EOpExp: out << "exp"; break;
321 case EOpLog: out << "log"; break;
322 case EOpExp2: out << "exp2"; break;
323 case EOpLog2: out << "log2"; break;
324 case EOpSqrt: out << "sqrt"; break;
325 case EOpInverseSqrt: out << "inverse sqrt"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700327 case EOpAbs: out << "Absolute value"; break;
328 case EOpSign: out << "Sign"; break;
329 case EOpFloor: out << "Floor"; break;
Qingqing Deng5dbece52015-02-27 20:35:38 -0800330 case EOpTrunc: out << "Truncate"; break;
331 case EOpRound: out << "Round"; break;
332 case EOpRoundEven: out << "Round half even"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700333 case EOpCeil: out << "Ceiling"; break;
334 case EOpFract: out << "Fraction"; break;
Arun Patole0c1726e2015-02-18 14:35:02 +0530335 case EOpIsNan: out << "Is not a number"; break;
336 case EOpIsInf: out << "Is infinity"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337
Olli Etuahoe8d2c072015-01-08 16:33:54 +0200338 case EOpFloatBitsToInt: out << "float bits to int"; break;
339 case EOpFloatBitsToUint: out << "float bits to uint"; break;
340 case EOpIntBitsToFloat: out << "int bits to float"; break;
341 case EOpUintBitsToFloat: out << "uint bits to float"; break;
342
Olli Etuaho7700ff62015-01-15 12:16:29 +0200343 case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break;
344 case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break;
345 case EOpPackHalf2x16: out << "pack half 2x16"; break;
346
347 case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break;
348 case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break;
349 case EOpUnpackHalf2x16: out << "unpack half 2x16"; break;
350
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700351 case EOpLength: out << "length"; break;
352 case EOpNormalize: out << "normalize"; break;
353 // case EOpDPdx: out << "dPdx"; break;
354 // case EOpDPdy: out << "dPdy"; break;
355 // case EOpFwidth: out << "fwidth"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356
Olli Etuahoe39706d2014-12-30 16:40:36 +0200357 case EOpDeterminant: out << "determinant"; break;
358 case EOpTranspose: out << "transpose"; break;
Olli Etuahoabf6dad2015-01-14 14:45:16 +0200359 case EOpInverse: out << "inverse"; break;
Olli Etuahoe39706d2014-12-30 16:40:36 +0200360
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700361 case EOpAny: out << "any"; break;
362 case EOpAll: out << "all"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700364 default:
365 out.prefix(EPrefixError);
366 out << "Bad unary op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000367 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368
alokp@chromium.org7beea402010-09-15 21:18:34 +0000369 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370
alokp@chromium.org7beea402010-09-15 21:18:34 +0000371 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372
alokp@chromium.org76b82082010-03-24 17:59:39 +0000373 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000374}
375
Olli Etuaho336b1472016-10-05 16:37:55 +0100376bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
377{
378 TInfoSinkBase &out = sink;
379 OutputTreeText(out, node, mDepth);
380 OutputFunction(out, "Function Definition", node->getFunctionSymbolInfo());
381 out << "\n";
382 return true;
383}
384
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700385bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700387 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100389 OutputTreeText(out, node, mDepth);
390
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700391 if (node->getOp() == EOpNull)
392 {
Jamie Madill075edd82013-07-08 13:30:19 -0400393 out.prefix(EPrefixError);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100394 out << "node is still EOpNull!\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000395 return true;
396 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700399 switch (node->getOp())
400 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700401 case EOpComma: out << "Comma\n"; return true;
Olli Etuaho336b1472016-10-05 16:37:55 +0100402 case EOpFunctionCall:
403 OutputFunction(out, "Function Call", node->getFunctionSymbolInfo());
404 break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700405 case EOpParameters: out << "Function Parameters: "; break;
Olli Etuaho336b1472016-10-05 16:37:55 +0100406 case EOpPrototype:
407 OutputFunction(out, "Function Prototype", node->getFunctionSymbolInfo());
408 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700410 case EOpConstructFloat: out << "Construct float"; break;
411 case EOpConstructVec2: out << "Construct vec2"; break;
412 case EOpConstructVec3: out << "Construct vec3"; break;
413 case EOpConstructVec4: out << "Construct vec4"; break;
414 case EOpConstructBool: out << "Construct bool"; break;
415 case EOpConstructBVec2: out << "Construct bvec2"; break;
416 case EOpConstructBVec3: out << "Construct bvec3"; break;
417 case EOpConstructBVec4: out << "Construct bvec4"; break;
418 case EOpConstructInt: out << "Construct int"; break;
419 case EOpConstructIVec2: out << "Construct ivec2"; break;
420 case EOpConstructIVec3: out << "Construct ivec3"; break;
421 case EOpConstructIVec4: out << "Construct ivec4"; break;
422 case EOpConstructUInt: out << "Construct uint"; break;
423 case EOpConstructUVec2: out << "Construct uvec2"; break;
424 case EOpConstructUVec3: out << "Construct uvec3"; break;
425 case EOpConstructUVec4: out << "Construct uvec4"; break;
426 case EOpConstructMat2: out << "Construct mat2"; break;
Alexis Hetu07e57df2015-06-16 16:55:52 -0400427 case EOpConstructMat2x3: out << "Construct mat2x3"; break;
428 case EOpConstructMat2x4: out << "Construct mat2x4"; break;
429 case EOpConstructMat3x2: out << "Construct mat3x2"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700430 case EOpConstructMat3: out << "Construct mat3"; break;
Alexis Hetu07e57df2015-06-16 16:55:52 -0400431 case EOpConstructMat3x4: out << "Construct mat3x4"; break;
432 case EOpConstructMat4x2: out << "Construct mat4x2"; break;
433 case EOpConstructMat4x3: out << "Construct mat4x3"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700434 case EOpConstructMat4: out << "Construct mat4"; break;
435 case EOpConstructStruct: out << "Construct structure"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000436
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700437 case EOpLessThan: out << "Compare Less Than"; break;
438 case EOpGreaterThan: out << "Compare Greater Than"; break;
439 case EOpLessThanEqual: out << "Compare Less Than or Equal"; break;
440 case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
441 case EOpVectorEqual: out << "Equal"; break;
442 case EOpVectorNotEqual: out << "NotEqual"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700444 case EOpMod: out << "mod"; break;
Olli Etuahob6e07a62015-02-16 12:22:10 +0200445 case EOpModf: out << "modf"; break;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700446 case EOpPow: out << "pow"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700448 case EOpAtan: out << "arc tangent"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700450 case EOpMin: out << "min"; break;
451 case EOpMax: out << "max"; break;
452 case EOpClamp: out << "clamp"; break;
453 case EOpMix: out << "mix"; break;
454 case EOpStep: out << "step"; break;
455 case EOpSmoothStep: out << "smoothstep"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700457 case EOpDistance: out << "distance"; break;
458 case EOpDot: out << "dot-product"; break;
459 case EOpCross: out << "cross-product"; break;
460 case EOpFaceForward: out << "face-forward"; break;
461 case EOpReflect: out << "reflect"; break;
462 case EOpRefract: out << "refract"; break;
463 case EOpMul: out << "component-wise multiply"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000464
Olli Etuahoe39706d2014-12-30 16:40:36 +0200465 case EOpOuterProduct: out << "outer product"; break;
466
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700467 case EOpDeclaration: out << "Declaration: "; break;
Jamie Madill3b5c2da2014-08-19 15:23:32 -0400468 case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
daniel@transgaming.coma9ae4aa2011-10-19 13:29:27 +0000469
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700470 default:
471 out.prefix(EPrefixError);
472 out << "Bad aggregation op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000473 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000474
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100475 if (node->getOp() != EOpParameters)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000476 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000477
alokp@chromium.org7beea402010-09-15 21:18:34 +0000478 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479
alokp@chromium.org76b82082010-03-24 17:59:39 +0000480 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481}
482
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100483bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
484{
485 TInfoSinkBase &out = sink;
486
487 OutputTreeText(out, node, mDepth);
488 out << "Code block\n";
489
490 return true;
491}
492
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300493bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
494{
495 TInfoSinkBase &out = sink;
496
497 OutputTreeText(out, node, mDepth);
498
499 out << "Ternary selection";
500 out << " (" << node->getCompleteString() << ")\n";
501
502 ++mDepth;
503
504 OutputTreeText(sink, node, mDepth);
505 out << "Condition\n";
506 node->getCondition()->traverse(this);
507
508 OutputTreeText(sink, node, mDepth);
509 if (node->getTrueExpression())
510 {
511 out << "true case\n";
512 node->getTrueExpression()->traverse(this);
513 }
514 if (node->getFalseExpression())
515 {
516 OutputTreeText(sink, node, mDepth);
517 out << "false case\n";
518 node->getFalseExpression()->traverse(this);
519 }
520
521 --mDepth;
522
523 return false;
524}
525
Olli Etuaho57961272016-09-14 13:57:46 +0300526bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700528 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000529
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700530 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000531
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300532 out << "If test\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000533
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700534 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000535
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700536 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000537 out << "Condition\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000538 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700540 OutputTreeText(sink, node, mDepth);
541 if (node->getTrueBlock())
542 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000543 out << "true case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000544 node->getTrueBlock()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700545 }
546 else
547 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000548 out << "true case is null\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700549 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000550
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700551 if (node->getFalseBlock())
552 {
553 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000554 out << "false case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000555 node->getFalseBlock()->traverse(this);
556 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000557
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700558 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559
alokp@chromium.org76b82082010-03-24 17:59:39 +0000560 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000561}
562
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700563void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000564{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700565 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000566
Jamie Madill94bf7f22013-07-08 13:31:15 -0400567 size_t size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700569 for (size_t i = 0; i < size; i++)
570 {
571 OutputTreeText(out, node, mDepth);
572 switch (node->getUnionArrayPointer()[i].getType())
573 {
574 case EbtBool:
575 if (node->getUnionArrayPointer()[i].getBConst())
576 out << "true";
577 else
578 out << "false";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700580 out << " (" << "const bool" << ")";
581 out << "\n";
582 break;
583 case EbtFloat:
584 out << node->getUnionArrayPointer()[i].getFConst();
585 out << " (const float)\n";
586 break;
587 case EbtInt:
588 out << node->getUnionArrayPointer()[i].getIConst();
589 out << " (const int)\n";
590 break;
591 case EbtUInt:
592 out << node->getUnionArrayPointer()[i].getUConst();
593 out << " (const uint)\n";
594 break;
595 default:
596 out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
597 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000598 }
599 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600}
601
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700602bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700604 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000605
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700606 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607
alokp@chromium.org7beea402010-09-15 21:18:34 +0000608 out << "Loop with condition ";
alokp@chromium.org52813552010-11-16 18:36:09 +0000609 if (node->getType() == ELoopDoWhile)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000610 out << "not ";
611 out << "tested first\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000612
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700613 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000614
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700615 OutputTreeText(sink, node, mDepth);
616 if (node->getCondition())
617 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000618 out << "Loop Condition\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000619 node->getCondition()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700620 }
621 else
622 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000623 out << "No loop condition\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700624 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000625
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700626 OutputTreeText(sink, node, mDepth);
627 if (node->getBody())
628 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000629 out << "Loop Body\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000630 node->getBody()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700631 }
632 else
633 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000634 out << "No loop body\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700635 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700637 if (node->getExpression())
638 {
639 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000640 out << "Loop Terminal Expression\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000641 node->getExpression()->traverse(this);
alokp@chromium.org76b82082010-03-24 17:59:39 +0000642 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700644 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645
alokp@chromium.org76b82082010-03-24 17:59:39 +0000646 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647}
648
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700649bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000650{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700651 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700653 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000654
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700655 switch (node->getFlowOp())
656 {
657 case EOpKill: out << "Branch: Kill"; break;
658 case EOpBreak: out << "Branch: Break"; break;
659 case EOpContinue: out << "Branch: Continue"; break;
660 case EOpReturn: out << "Branch: Return"; break;
661 default: out << "Branch: Unknown Branch"; break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000662 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700664 if (node->getExpression())
665 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000666 out << " with expression\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700667 ++mDepth;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000668 node->getExpression()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700669 --mDepth;
670 }
671 else
672 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000673 out << "\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700674 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675
alokp@chromium.org76b82082010-03-24 17:59:39 +0000676 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000677}
678
679//
680// This function is the one to call externally to start the traversal.
681// Individual functions can be initialized to 0 to skip processing of that
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200682// type of node. Its children will still be processed.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000683//
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200684void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000685{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200686 TOutputTraverser it(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000687
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200688 ASSERT(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689
alokp@chromium.org76b82082010-03-24 17:59:39 +0000690 root->traverse(&it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000691}