blob: b538f2b0962da7cfb8dcf9a690b0893b00b48f91 [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);
497 OutputFunction(out, "Function Definition", node->getFunctionSymbolInfo());
498 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;
540 case EOpParameters:
541 out << "Function Parameters: ";
542 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000543
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500544 case EOpConstructFloat:
545 out << "Construct float";
546 break;
547 case EOpConstructVec2:
548 out << "Construct vec2";
549 break;
550 case EOpConstructVec3:
551 out << "Construct vec3";
552 break;
553 case EOpConstructVec4:
554 out << "Construct vec4";
555 break;
556 case EOpConstructBool:
557 out << "Construct bool";
558 break;
559 case EOpConstructBVec2:
560 out << "Construct bvec2";
561 break;
562 case EOpConstructBVec3:
563 out << "Construct bvec3";
564 break;
565 case EOpConstructBVec4:
566 out << "Construct bvec4";
567 break;
568 case EOpConstructInt:
569 out << "Construct int";
570 break;
571 case EOpConstructIVec2:
572 out << "Construct ivec2";
573 break;
574 case EOpConstructIVec3:
575 out << "Construct ivec3";
576 break;
577 case EOpConstructIVec4:
578 out << "Construct ivec4";
579 break;
580 case EOpConstructUInt:
581 out << "Construct uint";
582 break;
583 case EOpConstructUVec2:
584 out << "Construct uvec2";
585 break;
586 case EOpConstructUVec3:
587 out << "Construct uvec3";
588 break;
589 case EOpConstructUVec4:
590 out << "Construct uvec4";
591 break;
592 case EOpConstructMat2:
593 out << "Construct mat2";
594 break;
595 case EOpConstructMat2x3:
596 out << "Construct mat2x3";
597 break;
598 case EOpConstructMat2x4:
599 out << "Construct mat2x4";
600 break;
601 case EOpConstructMat3x2:
602 out << "Construct mat3x2";
603 break;
604 case EOpConstructMat3:
605 out << "Construct mat3";
606 break;
607 case EOpConstructMat3x4:
608 out << "Construct mat3x4";
609 break;
610 case EOpConstructMat4x2:
611 out << "Construct mat4x2";
612 break;
613 case EOpConstructMat4x3:
614 out << "Construct mat4x3";
615 break;
616 case EOpConstructMat4:
617 out << "Construct mat4";
618 break;
619 case EOpConstructStruct:
620 out << "Construct structure";
621 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000622
Olli Etuahoe1805592017-01-02 16:41:20 +0000623 case EOpEqualComponentWise:
624 out << "component-wise equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500625 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000626 case EOpNotEqualComponentWise:
627 out << "component-wise not equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500628 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000629 case EOpLessThanComponentWise:
630 out << "component-wise less than";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500631 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000632 case EOpGreaterThanComponentWise:
633 out << "component-wise greater than";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500634 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000635 case EOpLessThanEqualComponentWise:
636 out << "component-wise less than or equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500637 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000638 case EOpGreaterThanEqualComponentWise:
639 out << "component-wise greater than or equal";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500640 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500642 case EOpMod:
643 out << "mod";
644 break;
645 case EOpModf:
646 out << "modf";
647 break;
648 case EOpPow:
649 out << "pow";
650 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500652 case EOpAtan:
653 out << "arc tangent";
654 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500656 case EOpMin:
657 out << "min";
658 break;
659 case EOpMax:
660 out << "max";
661 break;
662 case EOpClamp:
663 out << "clamp";
664 break;
665 case EOpMix:
666 out << "mix";
667 break;
668 case EOpStep:
669 out << "step";
670 break;
671 case EOpSmoothStep:
672 out << "smoothstep";
673 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000674
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500675 case EOpDistance:
676 out << "distance";
677 break;
678 case EOpDot:
679 out << "dot-product";
680 break;
681 case EOpCross:
682 out << "cross-product";
683 break;
684 case EOpFaceForward:
685 out << "face-forward";
686 break;
687 case EOpReflect:
688 out << "reflect";
689 break;
690 case EOpRefract:
691 out << "refract";
692 break;
Olli Etuahoe1805592017-01-02 16:41:20 +0000693 case EOpMulMatrixComponentWise:
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500694 out << "component-wise multiply";
695 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000696
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500697 case EOpOuterProduct:
698 out << "outer product";
699 break;
Olli Etuahoe39706d2014-12-30 16:40:36 +0200700
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500701 default:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000702 out.prefix(SH_ERROR);
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500703 out << "Bad aggregation op";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000704 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000705
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100706 if (node->getOp() != EOpParameters)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000707 out << " (" << node->getCompleteString() << ")";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000708
alokp@chromium.org7beea402010-09-15 21:18:34 +0000709 out << "\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000710
alokp@chromium.org76b82082010-03-24 17:59:39 +0000711 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712}
713
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100714bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
715{
716 TInfoSinkBase &out = sink;
717
718 OutputTreeText(out, node, mDepth);
719 out << "Code block\n";
720
721 return true;
722}
723
Olli Etuaho13389b62016-10-16 11:48:18 +0100724bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
725{
726 TInfoSinkBase &out = sink;
727
728 OutputTreeText(out, node, mDepth);
729 out << "Declaration\n";
730
731 return true;
732}
733
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300734bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
735{
736 TInfoSinkBase &out = sink;
737
738 OutputTreeText(out, node, mDepth);
739
740 out << "Ternary selection";
741 out << " (" << node->getCompleteString() << ")\n";
742
743 ++mDepth;
744
745 OutputTreeText(sink, node, mDepth);
746 out << "Condition\n";
747 node->getCondition()->traverse(this);
748
749 OutputTreeText(sink, node, mDepth);
750 if (node->getTrueExpression())
751 {
752 out << "true case\n";
753 node->getTrueExpression()->traverse(this);
754 }
755 if (node->getFalseExpression())
756 {
757 OutputTreeText(sink, node, mDepth);
758 out << "false case\n";
759 node->getFalseExpression()->traverse(this);
760 }
761
762 --mDepth;
763
764 return false;
765}
766
Olli Etuaho57961272016-09-14 13:57:46 +0300767bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000768{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700769 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700771 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300773 out << "If test\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000774
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700775 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000776
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700777 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000778 out << "Condition\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000779 node->getCondition()->traverse(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000780
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700781 OutputTreeText(sink, node, mDepth);
782 if (node->getTrueBlock())
783 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000784 out << "true case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000785 node->getTrueBlock()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700786 }
787 else
788 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000789 out << "true case is null\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700790 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000791
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700792 if (node->getFalseBlock())
793 {
794 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000795 out << "false case\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000796 node->getFalseBlock()->traverse(this);
797 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700799 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000800
alokp@chromium.org76b82082010-03-24 17:59:39 +0000801 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000802}
803
Olli Etuaho13e4d212016-10-13 11:50:27 +0100804bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
805{
806 TInfoSinkBase &out = sink;
807
808 OutputTreeText(out, node, mDepth);
809
810 out << "Switch\n";
811
812 return true;
813}
814
815bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
816{
817 TInfoSinkBase &out = sink;
818
819 OutputTreeText(out, node, mDepth);
820
821 if (node->getCondition() == nullptr)
822 {
823 out << "Default\n";
824 }
825 else
826 {
827 out << "Case\n";
828 }
829
830 return true;
831}
832
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700833void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000834{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700835 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000836
Jamie Madill94bf7f22013-07-08 13:31:15 -0400837 size_t size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000838
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700839 for (size_t i = 0; i < size; i++)
840 {
841 OutputTreeText(out, node, mDepth);
842 switch (node->getUnionArrayPointer()[i].getType())
843 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500844 case EbtBool:
845 if (node->getUnionArrayPointer()[i].getBConst())
846 out << "true";
847 else
848 out << "false";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000849
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500850 out << " ("
851 << "const bool"
852 << ")";
853 out << "\n";
854 break;
855 case EbtFloat:
856 out << node->getUnionArrayPointer()[i].getFConst();
857 out << " (const float)\n";
858 break;
859 case EbtInt:
860 out << node->getUnionArrayPointer()[i].getIConst();
861 out << " (const int)\n";
862 break;
863 case EbtUInt:
864 out << node->getUnionArrayPointer()[i].getUConst();
865 out << " (const uint)\n";
866 break;
867 default:
Olli Etuaho77ba4082016-12-16 12:01:18 +0000868 out.prefix(SH_ERROR);
869 out << "Unknown constant";
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500870 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000871 }
872 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000873}
874
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700875bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700877 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000878
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700879 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000880
alokp@chromium.org7beea402010-09-15 21:18:34 +0000881 out << "Loop with condition ";
alokp@chromium.org52813552010-11-16 18:36:09 +0000882 if (node->getType() == ELoopDoWhile)
alokp@chromium.org7beea402010-09-15 21:18:34 +0000883 out << "not ";
884 out << "tested first\n";
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700886 ++mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000887
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700888 OutputTreeText(sink, node, mDepth);
889 if (node->getCondition())
890 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000891 out << "Loop Condition\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000892 node->getCondition()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700893 }
894 else
895 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000896 out << "No loop condition\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700897 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000898
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700899 OutputTreeText(sink, node, mDepth);
900 if (node->getBody())
901 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000902 out << "Loop Body\n";
alokp@chromium.org76b82082010-03-24 17:59:39 +0000903 node->getBody()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700904 }
905 else
906 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000907 out << "No loop body\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700908 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000909
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700910 if (node->getExpression())
911 {
912 OutputTreeText(sink, node, mDepth);
alokp@chromium.org7beea402010-09-15 21:18:34 +0000913 out << "Loop Terminal Expression\n";
alokp@chromium.org52813552010-11-16 18:36:09 +0000914 node->getExpression()->traverse(this);
alokp@chromium.org76b82082010-03-24 17:59:39 +0000915 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700917 --mDepth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000918
alokp@chromium.org76b82082010-03-24 17:59:39 +0000919 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920}
921
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700922bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000923{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700924 TInfoSinkBase &out = sink;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000925
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700926 OutputTreeText(out, node, mDepth);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700928 switch (node->getFlowOp())
929 {
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500930 case EOpKill:
931 out << "Branch: Kill";
932 break;
933 case EOpBreak:
934 out << "Branch: Break";
935 break;
936 case EOpContinue:
937 out << "Branch: Continue";
938 break;
939 case EOpReturn:
940 out << "Branch: Return";
941 break;
942 default:
943 out << "Branch: Unknown Branch";
944 break;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000945 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700947 if (node->getExpression())
948 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000949 out << " with expression\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700950 ++mDepth;
alokp@chromium.org76b82082010-03-24 17:59:39 +0000951 node->getExpression()->traverse(this);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700952 --mDepth;
953 }
954 else
955 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000956 out << "\n";
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700957 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958
alokp@chromium.org76b82082010-03-24 17:59:39 +0000959 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000960}
961
962//
963// This function is the one to call externally to start the traversal.
964// Individual functions can be initialized to 0 to skip processing of that
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200965// type of node. Its children will still be processed.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966//
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200967void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968{
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200969 TOutputTraverser it(infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970
Olli Etuahoa3a5cc62015-02-13 13:12:22 +0200971 ASSERT(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972
alokp@chromium.org76b82082010-03-24 17:59:39 +0000973 root->traverse(&it);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974}
Jamie Madill45bcc782016-11-07 13:58:48 -0500975
976} // namespace sh