blob: 316bdfc5cbb0ebd644eb987852e918229cb50a02 [file] [log] [blame]
Olli Etuahocccf2b02017-07-05 14:50:54 +03001//
2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Olli Etuahocccf2b02017-07-05 14:50:54 +03007#include "compiler/translator/SymbolTable.h"
Olli Etuahoc26214d2018-03-16 10:43:11 +02008#include "compiler/translator/tree_util/IntermTraverse.h"
Olli Etuahocccf2b02017-07-05 14:50:54 +03009
10namespace sh
11{
12
13namespace
14{
15
Olli Etuaho1bb85282017-12-14 13:39:53 +020016void OutputFunction(TInfoSinkBase &out, const char *str, const TFunction *func)
17{
18 const char *internal =
19 (func->symbolType() == SymbolType::AngleInternal) ? " (internal function)" : "";
Olli Etuahobed35d72017-12-20 16:36:26 +020020 out << str << internal << ": " << func->name() << " (symbol id " << func->uniqueId().get()
Olli Etuaho1bb85282017-12-14 13:39:53 +020021 << ")";
22}
23
Olli Etuahocccf2b02017-07-05 14:50:54 +030024// Two purposes:
25// 1. Show an example of how to iterate tree. Functions can also directly call traverse() on
26// children themselves to have finer grained control over the process than shown here, though
27// that's not recommended if it can be avoided.
28// 2. Print out a text based description of the tree.
29
30// The traverser subclass is used to carry along data from node to node in the traversal.
31class TOutputTraverser : public TIntermTraverser
32{
33 public:
Olli Etuaho4002e922018-04-04 16:55:34 +030034 TOutputTraverser(TInfoSinkBase &out)
35 : TIntermTraverser(true, false, false), mOut(out), mIndentDepth(0)
36 {
37 }
Olli Etuahocccf2b02017-07-05 14:50:54 +030038
39 protected:
40 void visitSymbol(TIntermSymbol *) override;
41 void visitConstantUnion(TIntermConstantUnion *) override;
42 bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
43 bool visitBinary(Visit visit, TIntermBinary *) override;
44 bool visitUnary(Visit visit, TIntermUnary *) override;
45 bool visitTernary(Visit visit, TIntermTernary *node) override;
46 bool visitIfElse(Visit visit, TIntermIfElse *node) override;
47 bool visitSwitch(Visit visit, TIntermSwitch *node) override;
48 bool visitCase(Visit visit, TIntermCase *node) override;
Olli Etuahod4bd9632018-03-08 16:32:44 +020049 void visitFunctionPrototype(TIntermFunctionPrototype *node) override;
Olli Etuahocccf2b02017-07-05 14:50:54 +030050 bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
51 bool visitAggregate(Visit visit, TIntermAggregate *) override;
52 bool visitBlock(Visit visit, TIntermBlock *) override;
53 bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
54 bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
55 bool visitLoop(Visit visit, TIntermLoop *) override;
56 bool visitBranch(Visit visit, TIntermBranch *) override;
57
Olli Etuaho4002e922018-04-04 16:55:34 +030058 int getCurrentIndentDepth() const { return mIndentDepth + getCurrentTraversalDepth(); }
59
Olli Etuahocccf2b02017-07-05 14:50:54 +030060 TInfoSinkBase &mOut;
Olli Etuaho4002e922018-04-04 16:55:34 +030061 int mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +030062};
63
64//
65// Helper functions for printing, not part of traversing.
66//
67void OutputTreeText(TInfoSinkBase &out, TIntermNode *node, const int depth)
68{
69 int i;
70
71 out.location(node->getLine().first_file, node->getLine().first_line);
72
73 for (i = 0; i < depth; ++i)
74 out << " ";
75}
76
77//
78// 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
86void TOutputTraverser::visitSymbol(TIntermSymbol *node)
87{
Olli Etuaho4002e922018-04-04 16:55:34 +030088 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +030089
Olli Etuaho8b5e8fd2017-12-15 14:59:15 +020090 if (node->variable().symbolType() == SymbolType::Empty)
91 {
92 mOut << "''";
93 }
94 else
95 {
96 mOut << "'" << node->getName() << "' ";
97 }
Olli Etuahob6af22b2017-12-15 14:05:44 +020098 mOut << "(symbol id " << node->uniqueId().get() << ") ";
Olli Etuaho72e35892018-06-20 11:43:08 +030099 mOut << "(" << node->getType() << ")";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300100 mOut << "\n";
101}
102
103bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
104{
Olli Etuaho4002e922018-04-04 16:55:34 +0300105 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300106 mOut << "vector swizzle (";
107 node->writeOffsetsAsXYZW(&mOut);
108 mOut << ")";
109
Olli Etuaho72e35892018-06-20 11:43:08 +0300110 mOut << " (" << node->getType() << ")";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300111 mOut << "\n";
112 return true;
113}
114
115bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
116{
Olli Etuaho4002e922018-04-04 16:55:34 +0300117 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300118
119 switch (node->getOp())
120 {
121 case EOpComma:
122 mOut << "comma";
123 break;
124 case EOpAssign:
125 mOut << "move second child to first child";
126 break;
127 case EOpInitialize:
128 mOut << "initialize first child with second child";
129 break;
130 case EOpAddAssign:
131 mOut << "add second child into first child";
132 break;
133 case EOpSubAssign:
134 mOut << "subtract second child into first child";
135 break;
136 case EOpMulAssign:
137 mOut << "multiply second child into first child";
138 break;
139 case EOpVectorTimesMatrixAssign:
140 mOut << "matrix mult second child into first child";
141 break;
142 case EOpVectorTimesScalarAssign:
143 mOut << "vector scale second child into first child";
144 break;
145 case EOpMatrixTimesScalarAssign:
146 mOut << "matrix scale second child into first child";
147 break;
148 case EOpMatrixTimesMatrixAssign:
149 mOut << "matrix mult second child into first child";
150 break;
151 case EOpDivAssign:
152 mOut << "divide second child into first child";
153 break;
154 case EOpIModAssign:
155 mOut << "modulo second child into first child";
156 break;
157 case EOpBitShiftLeftAssign:
158 mOut << "bit-wise shift first child left by second child";
159 break;
160 case EOpBitShiftRightAssign:
161 mOut << "bit-wise shift first child right by second child";
162 break;
163 case EOpBitwiseAndAssign:
164 mOut << "bit-wise and second child into first child";
165 break;
166 case EOpBitwiseXorAssign:
167 mOut << "bit-wise xor second child into first child";
168 break;
169 case EOpBitwiseOrAssign:
170 mOut << "bit-wise or second child into first child";
171 break;
172
173 case EOpIndexDirect:
174 mOut << "direct index";
175 break;
176 case EOpIndexIndirect:
177 mOut << "indirect index";
178 break;
179 case EOpIndexDirectStruct:
180 mOut << "direct index for structure";
181 break;
182 case EOpIndexDirectInterfaceBlock:
183 mOut << "direct index for interface block";
184 break;
185
186 case EOpAdd:
187 mOut << "add";
188 break;
189 case EOpSub:
190 mOut << "subtract";
191 break;
192 case EOpMul:
193 mOut << "component-wise multiply";
194 break;
195 case EOpDiv:
196 mOut << "divide";
197 break;
198 case EOpIMod:
199 mOut << "modulo";
200 break;
201 case EOpBitShiftLeft:
202 mOut << "bit-wise shift left";
203 break;
204 case EOpBitShiftRight:
205 mOut << "bit-wise shift right";
206 break;
207 case EOpBitwiseAnd:
208 mOut << "bit-wise and";
209 break;
210 case EOpBitwiseXor:
211 mOut << "bit-wise xor";
212 break;
213 case EOpBitwiseOr:
214 mOut << "bit-wise or";
215 break;
216
217 case EOpEqual:
218 mOut << "Compare Equal";
219 break;
220 case EOpNotEqual:
221 mOut << "Compare Not Equal";
222 break;
223 case EOpLessThan:
224 mOut << "Compare Less Than";
225 break;
226 case EOpGreaterThan:
227 mOut << "Compare Greater Than";
228 break;
229 case EOpLessThanEqual:
230 mOut << "Compare Less Than or Equal";
231 break;
232 case EOpGreaterThanEqual:
233 mOut << "Compare Greater Than or Equal";
234 break;
235
236 case EOpVectorTimesScalar:
237 mOut << "vector-scale";
238 break;
239 case EOpVectorTimesMatrix:
240 mOut << "vector-times-matrix";
241 break;
242 case EOpMatrixTimesVector:
243 mOut << "matrix-times-vector";
244 break;
245 case EOpMatrixTimesScalar:
246 mOut << "matrix-scale";
247 break;
248 case EOpMatrixTimesMatrix:
249 mOut << "matrix-multiply";
250 break;
251
252 case EOpLogicalOr:
253 mOut << "logical-or";
254 break;
255 case EOpLogicalXor:
256 mOut << "logical-xor";
257 break;
258 case EOpLogicalAnd:
259 mOut << "logical-and";
260 break;
261 default:
262 mOut << "<unknown op>";
263 }
264
Olli Etuaho72e35892018-06-20 11:43:08 +0300265 mOut << " (" << node->getType() << ")";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300266
267 mOut << "\n";
268
269 // Special handling for direct indexes. Because constant
270 // unions are not aware they are struct indexes, treat them
271 // here where we have that contextual knowledge.
272 if (node->getOp() == EOpIndexDirectStruct || node->getOp() == EOpIndexDirectInterfaceBlock)
273 {
274 node->getLeft()->traverse(this);
275
276 TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
277 ASSERT(intermConstantUnion);
278
Olli Etuaho4002e922018-04-04 16:55:34 +0300279 OutputTreeText(mOut, intermConstantUnion, getCurrentIndentDepth() + 1);
Olli Etuahocccf2b02017-07-05 14:50:54 +0300280
281 // The following code finds the field name from the constant union
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200282 const TConstantUnion *constantUnion = intermConstantUnion->getConstantValue();
Olli Etuahocccf2b02017-07-05 14:50:54 +0300283 const TStructure *structure = node->getLeft()->getType().getStruct();
284 const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
285 ASSERT(structure || interfaceBlock);
286
287 const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
288
289 const TField *field = fields[constantUnion->getIConst()];
290
291 mOut << constantUnion->getIConst() << " (field '" << field->name() << "')";
292
293 mOut << "\n";
294
295 return false;
296 }
297
298 return true;
299}
300
301bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
302{
Olli Etuaho4002e922018-04-04 16:55:34 +0300303 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300304
305 switch (node->getOp())
306 {
307 // Give verbose names for ops that have special syntax and some built-in functions that are
308 // easy to confuse with others, but mostly use GLSL names for functions.
309 case EOpNegative:
310 mOut << "Negate value";
311 break;
312 case EOpPositive:
313 mOut << "Positive sign";
314 break;
315 case EOpLogicalNot:
316 mOut << "negation";
317 break;
318 case EOpBitwiseNot:
319 mOut << "bit-wise not";
320 break;
321
322 case EOpPostIncrement:
323 mOut << "Post-Increment";
324 break;
325 case EOpPostDecrement:
326 mOut << "Post-Decrement";
327 break;
328 case EOpPreIncrement:
329 mOut << "Pre-Increment";
330 break;
331 case EOpPreDecrement:
332 mOut << "Pre-Decrement";
333 break;
334
Olli Etuahobb2bbfb2017-08-24 15:43:33 +0300335 case EOpArrayLength:
336 mOut << "Array length";
337 break;
338
Olli Etuahocccf2b02017-07-05 14:50:54 +0300339 case EOpLogicalNotComponentWise:
340 mOut << "component-wise not";
341 break;
342
343 default:
344 mOut << GetOperatorString(node->getOp());
345 break;
346 }
347
Olli Etuaho72e35892018-06-20 11:43:08 +0300348 mOut << " (" << node->getType() << ")";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300349
350 mOut << "\n";
351
352 return true;
353}
354
355bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
356{
Olli Etuaho4002e922018-04-04 16:55:34 +0300357 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300358 mOut << "Function Definition:\n";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300359 return true;
360}
361
362bool TOutputTraverser::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
363{
Olli Etuaho4002e922018-04-04 16:55:34 +0300364 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300365 mOut << "Invariant Declaration:\n";
366 return true;
367}
368
Olli Etuahod4bd9632018-03-08 16:32:44 +0200369void TOutputTraverser::visitFunctionPrototype(TIntermFunctionPrototype *node)
Olli Etuahocccf2b02017-07-05 14:50:54 +0300370{
Olli Etuaho4002e922018-04-04 16:55:34 +0300371 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahobeb6dc72017-12-14 16:03:03 +0200372 OutputFunction(mOut, "Function Prototype", node->getFunction());
Olli Etuaho72e35892018-06-20 11:43:08 +0300373 mOut << " (" << node->getType() << ")";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300374 mOut << "\n";
Olli Etuahod4bd9632018-03-08 16:32:44 +0200375 size_t paramCount = node->getFunction()->getParamCount();
376 for (size_t i = 0; i < paramCount; ++i)
377 {
378 const TVariable *param = node->getFunction()->getParam(i);
Olli Etuaho4002e922018-04-04 16:55:34 +0300379 OutputTreeText(mOut, node, getCurrentIndentDepth() + 1);
Olli Etuaho72e35892018-06-20 11:43:08 +0300380 mOut << "parameter: " << param->name() << " (" << param->getType() << ")";
Olli Etuahod4bd9632018-03-08 16:32:44 +0200381 }
Olli Etuahocccf2b02017-07-05 14:50:54 +0300382}
383
384bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
385{
Olli Etuaho4002e922018-04-04 16:55:34 +0300386 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300387
388 if (node->getOp() == EOpNull)
389 {
390 mOut.prefix(SH_ERROR);
391 mOut << "node is still EOpNull!\n";
392 return true;
393 }
394
395 // Give verbose names for some built-in functions that are easy to confuse with others, but
396 // mostly use GLSL names for functions.
397 switch (node->getOp())
398 {
399 case EOpCallFunctionInAST:
Olli Etuaho1bb85282017-12-14 13:39:53 +0200400 OutputFunction(mOut, "Call an user-defined function", node->getFunction());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300401 break;
402 case EOpCallInternalRawFunction:
403 OutputFunction(mOut, "Call an internal function with raw implementation",
Olli Etuaho1bb85282017-12-14 13:39:53 +0200404 node->getFunction());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300405 break;
406 case EOpCallBuiltInFunction:
Olli Etuaho1bb85282017-12-14 13:39:53 +0200407 OutputFunction(mOut, "Call a built-in function", node->getFunction());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300408 break;
409
410 case EOpConstruct:
411 // The type of the constructor will be printed below.
412 mOut << "Construct";
413 break;
414
415 case EOpEqualComponentWise:
416 mOut << "component-wise equal";
417 break;
418 case EOpNotEqualComponentWise:
419 mOut << "component-wise not equal";
420 break;
421 case EOpLessThanComponentWise:
422 mOut << "component-wise less than";
423 break;
424 case EOpGreaterThanComponentWise:
425 mOut << "component-wise greater than";
426 break;
427 case EOpLessThanEqualComponentWise:
428 mOut << "component-wise less than or equal";
429 break;
430 case EOpGreaterThanEqualComponentWise:
431 mOut << "component-wise greater than or equal";
432 break;
433
434 case EOpDot:
435 mOut << "dot product";
436 break;
437 case EOpCross:
438 mOut << "cross product";
439 break;
440 case EOpMulMatrixComponentWise:
441 mOut << "component-wise multiply";
442 break;
443
444 default:
445 mOut << GetOperatorString(node->getOp());
446 break;
447 }
448
Olli Etuaho72e35892018-06-20 11:43:08 +0300449 mOut << " (" << node->getType() << ")";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300450
451 mOut << "\n";
452
453 return true;
454}
455
456bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
457{
Olli Etuaho4002e922018-04-04 16:55:34 +0300458 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300459 mOut << "Code block\n";
460
461 return true;
462}
463
464bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
465{
Olli Etuaho4002e922018-04-04 16:55:34 +0300466 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300467 mOut << "Declaration\n";
468
469 return true;
470}
471
472bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
473{
Olli Etuaho4002e922018-04-04 16:55:34 +0300474 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300475
476 mOut << "Ternary selection";
Olli Etuaho72e35892018-06-20 11:43:08 +0300477 mOut << " (" << node->getType() << ")\n";
Olli Etuahocccf2b02017-07-05 14:50:54 +0300478
Olli Etuaho4002e922018-04-04 16:55:34 +0300479 ++mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300480
Olli Etuaho4002e922018-04-04 16:55:34 +0300481 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300482 mOut << "Condition\n";
483 node->getCondition()->traverse(this);
484
Olli Etuaho4002e922018-04-04 16:55:34 +0300485 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300486 if (node->getTrueExpression())
487 {
488 mOut << "true case\n";
489 node->getTrueExpression()->traverse(this);
490 }
491 if (node->getFalseExpression())
492 {
Olli Etuaho4002e922018-04-04 16:55:34 +0300493 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300494 mOut << "false case\n";
495 node->getFalseExpression()->traverse(this);
496 }
497
Olli Etuaho4002e922018-04-04 16:55:34 +0300498 --mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300499
500 return false;
501}
502
503bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
504{
Olli Etuaho4002e922018-04-04 16:55:34 +0300505 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300506
507 mOut << "If test\n";
508
Olli Etuaho4002e922018-04-04 16:55:34 +0300509 ++mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300510
Olli Etuaho4002e922018-04-04 16:55:34 +0300511 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300512 mOut << "Condition\n";
513 node->getCondition()->traverse(this);
514
Olli Etuaho4002e922018-04-04 16:55:34 +0300515 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300516 if (node->getTrueBlock())
517 {
518 mOut << "true case\n";
519 node->getTrueBlock()->traverse(this);
520 }
521 else
522 {
523 mOut << "true case is null\n";
524 }
525
526 if (node->getFalseBlock())
527 {
Olli Etuaho4002e922018-04-04 16:55:34 +0300528 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300529 mOut << "false case\n";
530 node->getFalseBlock()->traverse(this);
531 }
532
Olli Etuaho4002e922018-04-04 16:55:34 +0300533 --mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300534
535 return false;
536}
537
538bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
539{
Olli Etuaho4002e922018-04-04 16:55:34 +0300540 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300541
542 mOut << "Switch\n";
543
544 return true;
545}
546
547bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
548{
Olli Etuaho4002e922018-04-04 16:55:34 +0300549 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300550
551 if (node->getCondition() == nullptr)
552 {
553 mOut << "Default\n";
554 }
555 else
556 {
557 mOut << "Case\n";
558 }
559
560 return true;
561}
562
563void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
564{
565 size_t size = node->getType().getObjectSize();
566
567 for (size_t i = 0; i < size; i++)
568 {
Olli Etuaho4002e922018-04-04 16:55:34 +0300569 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200570 switch (node->getConstantValue()[i].getType())
Olli Etuahocccf2b02017-07-05 14:50:54 +0300571 {
572 case EbtBool:
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200573 if (node->getConstantValue()[i].getBConst())
Olli Etuahocccf2b02017-07-05 14:50:54 +0300574 mOut << "true";
575 else
576 mOut << "false";
577
578 mOut << " ("
579 << "const bool"
580 << ")";
581 mOut << "\n";
582 break;
583 case EbtFloat:
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200584 mOut << node->getConstantValue()[i].getFConst();
Olli Etuahocccf2b02017-07-05 14:50:54 +0300585 mOut << " (const float)\n";
586 break;
587 case EbtInt:
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200588 mOut << node->getConstantValue()[i].getIConst();
Olli Etuahocccf2b02017-07-05 14:50:54 +0300589 mOut << " (const int)\n";
590 break;
591 case EbtUInt:
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200592 mOut << node->getConstantValue()[i].getUConst();
Olli Etuahocccf2b02017-07-05 14:50:54 +0300593 mOut << " (const uint)\n";
594 break;
595 case EbtYuvCscStandardEXT:
596 mOut << getYuvCscStandardEXTString(
Olli Etuahoea22b7a2018-01-04 17:09:11 +0200597 node->getConstantValue()[i].getYuvCscStandardEXTConst());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300598 mOut << " (const yuvCscStandardEXT)\n";
599 break;
600 default:
601 mOut.prefix(SH_ERROR);
602 mOut << "Unknown constant\n";
603 break;
604 }
605 }
606}
607
608bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
609{
Olli Etuaho4002e922018-04-04 16:55:34 +0300610 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300611
612 mOut << "Loop with condition ";
613 if (node->getType() == ELoopDoWhile)
614 mOut << "not ";
615 mOut << "tested first\n";
616
Olli Etuaho4002e922018-04-04 16:55:34 +0300617 ++mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300618
Olli Etuaho4002e922018-04-04 16:55:34 +0300619 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300620 if (node->getCondition())
621 {
622 mOut << "Loop Condition\n";
623 node->getCondition()->traverse(this);
624 }
625 else
626 {
627 mOut << "No loop condition\n";
628 }
629
Olli Etuaho4002e922018-04-04 16:55:34 +0300630 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300631 if (node->getBody())
632 {
633 mOut << "Loop Body\n";
634 node->getBody()->traverse(this);
635 }
636 else
637 {
638 mOut << "No loop body\n";
639 }
640
641 if (node->getExpression())
642 {
Olli Etuaho4002e922018-04-04 16:55:34 +0300643 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300644 mOut << "Loop Terminal Expression\n";
645 node->getExpression()->traverse(this);
646 }
647
Olli Etuaho4002e922018-04-04 16:55:34 +0300648 --mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300649
650 return false;
651}
652
653bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
654{
Olli Etuaho4002e922018-04-04 16:55:34 +0300655 OutputTreeText(mOut, node, getCurrentIndentDepth());
Olli Etuahocccf2b02017-07-05 14:50:54 +0300656
657 switch (node->getFlowOp())
658 {
659 case EOpKill:
660 mOut << "Branch: Kill";
661 break;
662 case EOpBreak:
663 mOut << "Branch: Break";
664 break;
665 case EOpContinue:
666 mOut << "Branch: Continue";
667 break;
668 case EOpReturn:
669 mOut << "Branch: Return";
670 break;
671 default:
672 mOut << "Branch: Unknown Branch";
673 break;
674 }
675
676 if (node->getExpression())
677 {
678 mOut << " with expression\n";
Olli Etuaho4002e922018-04-04 16:55:34 +0300679 ++mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300680 node->getExpression()->traverse(this);
Olli Etuaho4002e922018-04-04 16:55:34 +0300681 --mIndentDepth;
Olli Etuahocccf2b02017-07-05 14:50:54 +0300682 }
683 else
684 {
685 mOut << "\n";
686 }
687
688 return false;
689}
690
691} // anonymous namespace
692
693void OutputTree(TIntermNode *root, TInfoSinkBase &out)
694{
695 TOutputTraverser it(out);
696 ASSERT(root);
697 root->traverse(&it);
698}
699
700} // namespace sh