blob: 926967b26ff4668be191327220750d7ee96dcedf [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
Jamie Madill45bcc782016-11-07 13:58:48 -050010namespace sh
11{
12
Zhenyao Moe40d1e92014-07-16 17:40:36 -070013namespace
14{
15
Olli Etuaho336b1472016-10-05 16:37:55 +010016void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info)
Olli Etuaho5f579b12015-08-14 17:44:43 +030017{
Olli Etuaho336b1472016-10-05 16:37:55 +010018 const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
19 out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
20 << info->getId() << ")";
Olli Etuaho5f579b12015-08-14 17:44:43 +030021}
22
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023//
24// Two purposes:
25// 1. Show an example of how to iterate tree. Functions can
26// also directly call Traverse() on children themselves to
27// have finer grained control over the process than shown here.
28// See the last function for how to get started.
29// 2. Print out a text based description of the tree.
30//
31
32//
33// Use this class to carry along data from node to node in
34// the traversal
35//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070036class TOutputTraverser : public TIntermTraverser
37{
38 public:
Jamie Madilld7b1ab52016-12-12 14:42:19 -050039 TOutputTraverser(TInfoSinkBase &i) : TIntermTraverser(true, false, false), sink(i) {}
40 TInfoSinkBase &sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041
Zhenyao Moe40d1e92014-07-16 17:40:36 -070042 protected:
Corentin Walleze5a1f272015-08-21 02:58:25 +020043 void visitSymbol(TIntermSymbol *) override;
44 void visitConstantUnion(TIntermConstantUnion *) override;
Olli Etuahob6fa0432016-09-28 16:28:05 +010045 bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020046 bool visitBinary(Visit visit, TIntermBinary *) override;
47 bool visitUnary(Visit visit, TIntermUnary *) override;
Olli Etuahod0bad2c2016-09-09 18:01:16 +030048 bool visitTernary(Visit visit, TIntermTernary *node) override;
Olli Etuaho57961272016-09-14 13:57:46 +030049 bool visitIfElse(Visit visit, TIntermIfElse *node) override;
Olli Etuaho13e4d212016-10-13 11:50:27 +010050 bool visitSwitch(Visit visit, TIntermSwitch *node) override;
51 bool visitCase(Visit visit, TIntermCase *node) override;
Olli Etuaho16c745a2017-01-16 17:02:27 +000052 bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *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;
Olli Etuahobf4e1b72016-12-09 11:30:15 +000056 bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
Olli Etuaho13389b62016-10-16 11:48:18 +010057 bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
Corentin Walleze5a1f272015-08-21 02:58:25 +020058 bool visitLoop(Visit visit, TIntermLoop *) override;
59 bool visitBranch(Visit visit, TIntermBranch *) override;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000060};
61
Zhenyao Moe40d1e92014-07-16 17:40:36 -070062//
63// Helper functions for printing, not part of traversing.
64//
65void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
66{
67 int i;
68
Olli Etuaho77ba4082016-12-16 12:01:18 +000069 sink.location(node->getLine().first_file, node->getLine().first_line);
Zhenyao Moe40d1e92014-07-16 17:40:36 -070070
71 for (i = 0; i < depth; ++i)
72 sink << " ";
73}
74
75} // namespace anonymous
76
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000078// The rest of the file are the traversal functions. The last one
79// is the one that starts the traversal.
80//
81// Return true from interior nodes to have the external traversal
82// continue on to children. If you process children yourself,
83// return false.
84//
85
Zhenyao Moe40d1e92014-07-16 17:40:36 -070086void TOutputTraverser::visitSymbol(TIntermSymbol *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070088 OutputTreeText(sink, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089
alokp@chromium.org7beea402010-09-15 21:18:34 +000090 sink << "'" << node->getSymbol() << "' ";
91 sink << "(" << node->getCompleteString() << ")\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092}
93
Olli Etuahob6fa0432016-09-28 16:28:05 +010094bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
95{
96 TInfoSinkBase &out = sink;
97 OutputTreeText(out, node, mDepth);
98 out << "vector swizzle";
99 return true;
100}
101
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700102bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500104 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700106 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700108 switch (node->getOp())
109 {
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100110 case EOpComma:
111 out << "comma";
112 break;
113 case EOpAssign:
114 out << "move second child to first child";
115 break;
116 case EOpInitialize:
117 out << "initialize first child with second child";
118 break;
119 case EOpAddAssign:
120 out << "add second child into first child";
121 break;
122 case EOpSubAssign:
123 out << "subtract second child into first child";
124 break;
125 case EOpMulAssign:
126 out << "multiply second child into first child";
127 break;
128 case EOpVectorTimesMatrixAssign:
129 out << "matrix mult second child into first child";
130 break;
131 case EOpVectorTimesScalarAssign:
132 out << "vector scale second child into first child";
133 break;
134 case EOpMatrixTimesScalarAssign:
135 out << "matrix scale second child into first child";
136 break;
137 case EOpMatrixTimesMatrixAssign:
138 out << "matrix mult second child into first child";
139 break;
140 case EOpDivAssign:
141 out << "divide second child into first child";
142 break;
143 case EOpIModAssign:
144 out << "modulo second child into first child";
145 break;
146 case EOpBitShiftLeftAssign:
147 out << "bit-wise shift first child left by second child";
148 break;
149 case EOpBitShiftRightAssign:
150 out << "bit-wise shift first child right by second child";
151 break;
152 case EOpBitwiseAndAssign:
153 out << "bit-wise and second child into first child";
154 break;
155 case EOpBitwiseXorAssign:
156 out << "bit-wise xor second child into first child";
157 break;
158 case EOpBitwiseOrAssign:
159 out << "bit-wise or second child into first child";
160 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200161
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100162 case EOpIndexDirect:
163 out << "direct index";
164 break;
165 case EOpIndexIndirect:
166 out << "indirect index";
167 break;
168 case EOpIndexDirectStruct:
169 out << "direct index for structure";
170 break;
171 case EOpIndexDirectInterfaceBlock:
172 out << "direct index for interface block";
173 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100175 case EOpAdd:
176 out << "add";
177 break;
178 case EOpSub:
179 out << "subtract";
180 break;
181 case EOpMul:
182 out << "component-wise multiply";
183 break;
184 case EOpDiv:
185 out << "divide";
186 break;
187 case EOpIMod:
188 out << "modulo";
189 break;
190 case EOpBitShiftLeft:
191 out << "bit-wise shift left";
192 break;
193 case EOpBitShiftRight:
194 out << "bit-wise shift right";
195 break;
196 case EOpBitwiseAnd:
197 out << "bit-wise and";
198 break;
199 case EOpBitwiseXor:
200 out << "bit-wise xor";
201 break;
202 case EOpBitwiseOr:
203 out << "bit-wise or";
204 break;
Olli Etuaho31b5fc62015-01-16 12:13:36 +0200205
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100206 case EOpEqual:
207 out << "Compare Equal";
208 break;
209 case EOpNotEqual:
210 out << "Compare Not Equal";
211 break;
212 case EOpLessThan:
213 out << "Compare Less Than";
214 break;
215 case EOpGreaterThan:
216 out << "Compare Greater Than";
217 break;
218 case EOpLessThanEqual:
219 out << "Compare Less Than or Equal";
220 break;
221 case EOpGreaterThanEqual:
222 out << "Compare Greater Than or Equal";
223 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100225 case EOpVectorTimesScalar:
226 out << "vector-scale";
227 break;
228 case EOpVectorTimesMatrix:
229 out << "vector-times-matrix";
230 break;
231 case EOpMatrixTimesVector:
232 out << "matrix-times-vector";
233 break;
234 case EOpMatrixTimesScalar:
235 out << "matrix-scale";
236 break;
237 case EOpMatrixTimesMatrix:
238 out << "matrix-multiply";
239 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100241 case EOpLogicalOr:
242 out << "logical-or";
243 break;
244 case EOpLogicalXor:
245 out << "logical-xor";
246 break;
247 case EOpLogicalAnd:
248 out << "logical-and";
249 break;
250 default:
251 out << "<unknown op>";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000252 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253
alokp@chromium.org7beea402010-09-15 21:18:34 +0000254 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
alokp@chromium.org7beea402010-09-15 21:18:34 +0000256 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257
Jamie Madill60305f12014-11-18 13:25:26 -0500258 // Special handling for direct indexes. Because constant
259 // unions are not aware they are struct indexes, treat them
260 // here where we have that contextual knowledge.
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500261 if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock)
Jamie Madill60305f12014-11-18 13:25:26 -0500262 {
263 mDepth++;
264 node->getLeft()->traverse(this);
265 mDepth--;
266
267 TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
268 ASSERT(intermConstantUnion);
269
270 OutputTreeText(out, intermConstantUnion, mDepth + 1);
271
272 // The following code finds the field name from the constant union
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500273 const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
274 const TStructure *structure = node->getLeft()->getType().getStruct();
Jamie Madill60305f12014-11-18 13:25:26 -0500275 const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
276 ASSERT(structure || interfaceBlock);
277
278 const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
279
280 const TField *field = fields[constantUnion->getIConst()];
281
282 out << constantUnion->getIConst() << " (field '" << field->name() << "')";
283
284 return false;
285 }
286
alokp@chromium.org76b82082010-03-24 17:59:39 +0000287 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288}
289
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700290bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291{
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500292 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700294 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700296 switch (node->getOp())
297 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500298 case EOpNegative:
299 out << "Negate value";
300 break;
301 case EOpPositive:
302 out << "Positive sign";
303 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500304 case EOpLogicalNot:
Olli Etuahod68924e2017-01-02 17:34:40 +0000305 out << "negation";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500306 break;
307 case EOpBitwiseNot:
308 out << "bit-wise not";
309 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500311 case EOpPostIncrement:
312 out << "Post-Increment";
313 break;
314 case EOpPostDecrement:
315 out << "Post-Decrement";
316 break;
317 case EOpPreIncrement:
318 out << "Pre-Increment";
319 break;
320 case EOpPreDecrement:
321 out << "Pre-Decrement";
322 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500324 case EOpRadians:
325 out << "radians";
326 break;
327 case EOpDegrees:
328 out << "degrees";
329 break;
330 case EOpSin:
331 out << "sine";
332 break;
333 case EOpCos:
334 out << "cosine";
335 break;
336 case EOpTan:
337 out << "tangent";
338 break;
339 case EOpAsin:
340 out << "arc sine";
341 break;
342 case EOpAcos:
343 out << "arc cosine";
344 break;
345 case EOpAtan:
346 out << "arc tangent";
347 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500349 case EOpSinh:
350 out << "hyperbolic sine";
351 break;
352 case EOpCosh:
353 out << "hyperbolic cosine";
354 break;
355 case EOpTanh:
356 out << "hyperbolic tangent";
357 break;
358 case EOpAsinh:
359 out << "arc hyperbolic sine";
360 break;
361 case EOpAcosh:
362 out << "arc hyperbolic cosine";
363 break;
364 case EOpAtanh:
365 out << "arc hyperbolic tangent";
366 break;
Olli Etuaho5c9cd3d2014-12-18 13:04:25 +0200367
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500368 case EOpExp:
369 out << "exp";
370 break;
371 case EOpLog:
372 out << "log";
373 break;
374 case EOpExp2:
375 out << "exp2";
376 break;
377 case EOpLog2:
378 out << "log2";
379 break;
380 case EOpSqrt:
381 out << "sqrt";
382 break;
383 case EOpInverseSqrt:
384 out << "inverse sqrt";
385 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500387 case EOpAbs:
388 out << "Absolute value";
389 break;
390 case EOpSign:
391 out << "Sign";
392 break;
393 case EOpFloor:
394 out << "Floor";
395 break;
396 case EOpTrunc:
397 out << "Truncate";
398 break;
399 case EOpRound:
400 out << "Round";
401 break;
402 case EOpRoundEven:
403 out << "Round half even";
404 break;
405 case EOpCeil:
406 out << "Ceiling";
407 break;
408 case EOpFract:
409 out << "Fraction";
410 break;
411 case EOpIsNan:
412 out << "Is not a number";
413 break;
414 case EOpIsInf:
415 out << "Is infinity";
416 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000417
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500418 case EOpFloatBitsToInt:
419 out << "float bits to int";
420 break;
421 case EOpFloatBitsToUint:
422 out << "float bits to uint";
423 break;
424 case EOpIntBitsToFloat:
425 out << "int bits to float";
426 break;
427 case EOpUintBitsToFloat:
428 out << "uint bits to float";
429 break;
Olli Etuahoe8d2c072015-01-08 16:33:54 +0200430
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500431 case EOpPackSnorm2x16:
432 out << "pack Snorm 2x16";
433 break;
434 case EOpPackUnorm2x16:
435 out << "pack Unorm 2x16";
436 break;
437 case EOpPackHalf2x16:
438 out << "pack half 2x16";
439 break;
Olli Etuaho7700ff62015-01-15 12:16:29 +0200440
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500441 case EOpUnpackSnorm2x16:
442 out << "unpack Snorm 2x16";
443 break;
444 case EOpUnpackUnorm2x16:
445 out << "unpack Unorm 2x16";
446 break;
447 case EOpUnpackHalf2x16:
448 out << "unpack half 2x16";
449 break;
Olli Etuaho7700ff62015-01-15 12:16:29 +0200450
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500451 case EOpLength:
452 out << "length";
453 break;
454 case EOpNormalize:
455 out << "normalize";
456 break;
457 // case EOpDPdx: out << "dPdx"; break;
458 // case EOpDPdy: out << "dPdy"; break;
459 // case EOpFwidth: out << "fwidth"; break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500461 case EOpDeterminant:
462 out << "determinant";
463 break;
464 case EOpTranspose:
465 out << "transpose";
466 break;
467 case EOpInverse:
468 out << "inverse";
469 break;
Olli Etuahoe39706d2014-12-30 16:40:36 +0200470
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500471 case EOpAny:
472 out << "any";
473 break;
474 case EOpAll:
475 out << "all";
476 break;
Olli Etuahod68924e2017-01-02 17:34:40 +0000477 case EOpLogicalNotComponentWise:
478 out << "component-wise not";
479 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000480
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500481 default:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000482 out.prefix(SH_ERROR);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500483 out << "Bad unary op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000484 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000485
alokp@chromium.org7beea402010-09-15 21:18:34 +0000486 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487
alokp@chromium.org7beea402010-09-15 21:18:34 +0000488 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489
alokp@chromium.org76b82082010-03-24 17:59:39 +0000490 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491}
492
Olli Etuaho336b1472016-10-05 16:37:55 +0100493bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
494{
495 TInfoSinkBase &out = sink;
496 OutputTreeText(out, node, mDepth);
Olli Etuaho8ad9e752017-01-16 19:55:20 +0000497 out << "Function Definition:\n";
Olli Etuaho336b1472016-10-05 16:37:55 +0100498 out << "\n";
499 return true;
500}
501
Olli Etuahobf4e1b72016-12-09 11:30:15 +0000502bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
503{
504 TInfoSinkBase &out = sink;
505 OutputTreeText(out, node, mDepth);
506 out << "Invariant Declaration:\n";
507 return true;
508}
509
Olli Etuaho16c745a2017-01-16 17:02:27 +0000510bool TOutputTraverser::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
511{
512 TInfoSinkBase &out = sink;
513
514 OutputTreeText(out, node, mDepth);
515 OutputFunction(out, "Function Prototype", node->getFunctionSymbolInfo());
516 out << " (" << node->getCompleteString() << ")";
517 out << "\n";
518
519 return true;
520}
521
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700522bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700524 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000525
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100526 OutputTreeText(out, node, mDepth);
527
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700528 if (node->getOp() == EOpNull)
529 {
Olli Etuaho77ba4082016-12-16 12:01:18 +0000530 out.prefix(SH_ERROR);
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100531 out << "node is still EOpNull!\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000532 return true;
533 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700535 switch (node->getOp())
536 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500537 case EOpFunctionCall:
538 OutputFunction(out, "Function Call", node->getFunctionSymbolInfo());
539 break;
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500540 case EOpConstructFloat:
541 out << "Construct float";
542 break;
543 case EOpConstructVec2:
544 out << "Construct vec2";
545 break;
546 case EOpConstructVec3:
547 out << "Construct vec3";
548 break;
549 case EOpConstructVec4:
550 out << "Construct vec4";
551 break;
552 case EOpConstructBool:
553 out << "Construct bool";
554 break;
555 case EOpConstructBVec2:
556 out << "Construct bvec2";
557 break;
558 case EOpConstructBVec3:
559 out << "Construct bvec3";
560 break;
561 case EOpConstructBVec4:
562 out << "Construct bvec4";
563 break;
564 case EOpConstructInt:
565 out << "Construct int";
566 break;
567 case EOpConstructIVec2:
568 out << "Construct ivec2";
569 break;
570 case EOpConstructIVec3:
571 out << "Construct ivec3";
572 break;
573 case EOpConstructIVec4:
574 out << "Construct ivec4";
575 break;
576 case EOpConstructUInt:
577 out << "Construct uint";
578 break;
579 case EOpConstructUVec2:
580 out << "Construct uvec2";
581 break;
582 case EOpConstructUVec3:
583 out << "Construct uvec3";
584 break;
585 case EOpConstructUVec4:
586 out << "Construct uvec4";
587 break;
588 case EOpConstructMat2:
589 out << "Construct mat2";
590 break;
591 case EOpConstructMat2x3:
592 out << "Construct mat2x3";
593 break;
594 case EOpConstructMat2x4:
595 out << "Construct mat2x4";
596 break;
597 case EOpConstructMat3x2:
598 out << "Construct mat3x2";
599 break;
600 case EOpConstructMat3:
601 out << "Construct mat3";
602 break;
603 case EOpConstructMat3x4:
604 out << "Construct mat3x4";
605 break;
606 case EOpConstructMat4x2:
607 out << "Construct mat4x2";
608 break;
609 case EOpConstructMat4x3:
610 out << "Construct mat4x3";
611 break;
612 case EOpConstructMat4:
613 out << "Construct mat4";
614 break;
615 case EOpConstructStruct:
616 out << "Construct structure";
617 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000618
Olli Etuahoe1805592017-01-02 16:41:20 +0000619 case EOpEqualComponentWise:
620 out << "component-wise equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500621 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000622 case EOpNotEqualComponentWise:
623 out << "component-wise not equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500624 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000625 case EOpLessThanComponentWise:
626 out << "component-wise less than";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500627 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000628 case EOpGreaterThanComponentWise:
629 out << "component-wise greater than";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500630 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000631 case EOpLessThanEqualComponentWise:
632 out << "component-wise less than or equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500633 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000634 case EOpGreaterThanEqualComponentWise:
635 out << "component-wise greater than or equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500636 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500638 case EOpMod:
639 out << "mod";
640 break;
641 case EOpModf:
642 out << "modf";
643 break;
644 case EOpPow:
645 out << "pow";
646 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500648 case EOpAtan:
649 out << "arc tangent";
650 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500652 case EOpMin:
653 out << "min";
654 break;
655 case EOpMax:
656 out << "max";
657 break;
658 case EOpClamp:
659 out << "clamp";
660 break;
661 case EOpMix:
662 out << "mix";
663 break;
664 case EOpStep:
665 out << "step";
666 break;
667 case EOpSmoothStep:
668 out << "smoothstep";
669 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500671 case EOpDistance:
672 out << "distance";
673 break;
674 case EOpDot:
675 out << "dot-product";
676 break;
677 case EOpCross:
678 out << "cross-product";
679 break;
680 case EOpFaceForward:
681 out << "face-forward";
682 break;
683 case EOpReflect:
684 out << "reflect";
685 break;
686 case EOpRefract:
687 out << "refract";
688 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000689 case EOpMulMatrixComponentWise:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500690 out << "component-wise multiply";
691 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000692
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500693 case EOpOuterProduct:
694 out << "outer product";
695 break;
Olli Etuahoe39706d2014-12-30 16:40:36 +0200696
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500697 default:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000698 out.prefix(SH_ERROR);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500699 out << "Bad aggregation op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000700 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000701
Olli Etuaho8ad9e752017-01-16 19:55:20 +0000702 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000703
alokp@chromium.org7beea402010-09-15 21:18:34 +0000704 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705
alokp@chromium.org76b82082010-03-24 17:59:39 +0000706 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000707}
708
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100709bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
710{
711 TInfoSinkBase &out = sink;
712
713 OutputTreeText(out, node, mDepth);
714 out << "Code block\n";
715
716 return true;
717}
718
Olli Etuaho13389b62016-10-16 11:48:18 +0100719bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
720{
721 TInfoSinkBase &out = sink;
722
723 OutputTreeText(out, node, mDepth);
724 out << "Declaration\n";
725
726 return true;
727}
728
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300729bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
730{
731 TInfoSinkBase &out = sink;
732
733 OutputTreeText(out, node, mDepth);
734
735 out << "Ternary selection";
736 out << " (" << node->getCompleteString() << ")\n";
737
738 ++mDepth;
739
740 OutputTreeText(sink, node, mDepth);
741 out << "Condition\n";
742 node->getCondition()->traverse(this);
743
744 OutputTreeText(sink, node, mDepth);
745 if (node->getTrueExpression())
746 {
747 out << "true case\n";
748 node->getTrueExpression()->traverse(this);
749 }
750 if (node->getFalseExpression())
751 {
752 OutputTreeText(sink, node, mDepth);
753 out << "false case\n";
754 node->getFalseExpression()->traverse(this);
755 }
756
757 --mDepth;
758
759 return false;
760}
761
Olli Etuaho57961272016-09-14 13:57:46 +0300762bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000763{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700764 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000765
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700766 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000767
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300768 out << "If test\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000769
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700770 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000771
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700772 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000773 out << "Condition\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000774 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000775
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700776 OutputTreeText(sink, node, mDepth);
777 if (node->getTrueBlock())
778 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000779 out << "true case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000780 node->getTrueBlock()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700781 }
782 else
783 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000784 out << "true case is null\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700785 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700787 if (node->getFalseBlock())
788 {
789 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000790 out << "false case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000791 node->getFalseBlock()->traverse(this);
792 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700794 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795
alokp@chromium.org76b82082010-03-24 17:59:39 +0000796 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797}
798
Olli Etuaho13e4d212016-10-13 11:50:27 +0100799bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
800{
801 TInfoSinkBase &out = sink;
802
803 OutputTreeText(out, node, mDepth);
804
805 out << "Switch\n";
806
807 return true;
808}
809
810bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
811{
812 TInfoSinkBase &out = sink;
813
814 OutputTreeText(out, node, mDepth);
815
816 if (node->getCondition() == nullptr)
817 {
818 out << "Default\n";
819 }
820 else
821 {
822 out << "Case\n";
823 }
824
825 return true;
826}
827
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700828void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000829{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700830 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831
Jamie Madill94bf7f22013-07-08 13:31:15 -0400832 size_t size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000833
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700834 for (size_t i = 0; i < size; i++)
835 {
836 OutputTreeText(out, node, mDepth);
837 switch (node->getUnionArrayPointer()[i].getType())
838 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500839 case EbtBool:
840 if (node->getUnionArrayPointer()[i].getBConst())
841 out << "true";
842 else
843 out << "false";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000844
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500845 out << " ("
846 << "const bool"
847 << ")";
848 out << "\n";
849 break;
850 case EbtFloat:
851 out << node->getUnionArrayPointer()[i].getFConst();
852 out << " (const float)\n";
853 break;
854 case EbtInt:
855 out << node->getUnionArrayPointer()[i].getIConst();
856 out << " (const int)\n";
857 break;
858 case EbtUInt:
859 out << node->getUnionArrayPointer()[i].getUConst();
860 out << " (const uint)\n";
861 break;
862 default:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000863 out.prefix(SH_ERROR);
864 out << "Unknown constant";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500865 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000866 }
867 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000868}
869
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700870bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000871{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700872 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000873
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700874 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000875
alokp@chromium.org7beea402010-09-15 21:18:34 +0000876 out << "Loop with condition ";
alokp@chromium.org52813552010-11-16 18:36:09 +0000877 if (node->getType() == ELoopDoWhile)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000878 out << "not ";
879 out << "tested first\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000880
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700881 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700883 OutputTreeText(sink, node, mDepth);
884 if (node->getCondition())
885 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000886 out << "Loop Condition\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000887 node->getCondition()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700888 }
889 else
890 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000891 out << "No loop condition\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700892 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000893
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700894 OutputTreeText(sink, node, mDepth);
895 if (node->getBody())
896 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000897 out << "Loop Body\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000898 node->getBody()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700899 }
900 else
901 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000902 out << "No loop body\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700903 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000904
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700905 if (node->getExpression())
906 {
907 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000908 out << "Loop Terminal Expression\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000909 node->getExpression()->traverse(this);
alokp@chromium.org76b82082010-03-24 17:59:39 +0000910 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000911
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700912 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000913
alokp@chromium.org76b82082010-03-24 17:59:39 +0000914 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000915}
916
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700917bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000918{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700919 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700921 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000922
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700923 switch (node->getFlowOp())
924 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500925 case EOpKill:
926 out << "Branch: Kill";
927 break;
928 case EOpBreak:
929 out << "Branch: Break";
930 break;
931 case EOpContinue:
932 out << "Branch: Continue";
933 break;
934 case EOpReturn:
935 out << "Branch: Return";
936 break;
937 default:
938 out << "Branch: Unknown Branch";
939 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000940 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000941
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700942 if (node->getExpression())
943 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000944 out << " with expression\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700945 ++mDepth;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000946 node->getExpression()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700947 --mDepth;
948 }
949 else
950 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000951 out << "\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700952 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953
alokp@chromium.org76b82082010-03-24 17:59:39 +0000954 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000955}
956
957//
958// This function is the one to call externally to start the traversal.
959// Individual functions can be initialized to 0 to skip processing of that
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200960// type of node. Its children will still be processed.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000961//
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200962void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200964 TOutputTraverser it(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200966 ASSERT(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000967
alokp@chromium.org76b82082010-03-24 17:59:39 +0000968 root->traverse(&it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969}
Jamie Madill45bcc782016-11-07 13:58:48 -0500970
971} // namespace sh