Line data Source code
1 : //
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 :
7 : #include "compiler/translator/Intermediate.h"
8 : #include "compiler/translator/SymbolTable.h"
9 :
10 : namespace sh
11 : {
12 :
13 : namespace
14 : {
15 :
16 0 : void OutputFunction(TInfoSinkBase &out, const char *str, TFunctionSymbolInfo *info)
17 : {
18 0 : const char *internal = info->getNameObj().isInternal() ? " (internal function)" : "";
19 0 : out << str << internal << ": " << info->getNameObj().getString() << " (symbol id "
20 0 : << info->getId() << ")";
21 0 : }
22 :
23 : //
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 : //
36 0 : class TOutputTraverser : public TIntermTraverser
37 : {
38 : public:
39 0 : TOutputTraverser(TInfoSinkBase &i)
40 0 : : TIntermTraverser(true, false, false),
41 0 : sink(i)
42 : {
43 0 : }
44 : TInfoSinkBase& sink;
45 :
46 : protected:
47 : void visitSymbol(TIntermSymbol *) override;
48 : void visitConstantUnion(TIntermConstantUnion *) override;
49 : bool visitSwizzle(Visit visit, TIntermSwizzle *node) override;
50 : bool visitBinary(Visit visit, TIntermBinary *) override;
51 : bool visitUnary(Visit visit, TIntermUnary *) override;
52 : bool visitTernary(Visit visit, TIntermTernary *node) override;
53 : bool visitIfElse(Visit visit, TIntermIfElse *node) override;
54 : bool visitSwitch(Visit visit, TIntermSwitch *node) override;
55 : bool visitCase(Visit visit, TIntermCase *node) override;
56 : bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
57 : bool visitAggregate(Visit visit, TIntermAggregate *) override;
58 : bool visitBlock(Visit visit, TIntermBlock *) override;
59 : bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
60 : bool visitLoop(Visit visit, TIntermLoop *) override;
61 : bool visitBranch(Visit visit, TIntermBranch *) override;
62 : };
63 :
64 : //
65 : // Helper functions for printing, not part of traversing.
66 : //
67 0 : void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth)
68 : {
69 : int i;
70 :
71 0 : sink.location(node->getLine());
72 :
73 0 : for (i = 0; i < depth; ++i)
74 0 : sink << " ";
75 0 : }
76 :
77 : } // namespace anonymous
78 :
79 : //
80 : // The rest of the file are the traversal functions. The last one
81 : // is the one that starts the traversal.
82 : //
83 : // Return true from interior nodes to have the external traversal
84 : // continue on to children. If you process children yourself,
85 : // return false.
86 : //
87 :
88 0 : void TOutputTraverser::visitSymbol(TIntermSymbol *node)
89 : {
90 0 : OutputTreeText(sink, node, mDepth);
91 :
92 0 : sink << "'" << node->getSymbol() << "' ";
93 0 : sink << "(" << node->getCompleteString() << ")\n";
94 0 : }
95 :
96 0 : bool TOutputTraverser::visitSwizzle(Visit visit, TIntermSwizzle *node)
97 : {
98 0 : TInfoSinkBase &out = sink;
99 0 : OutputTreeText(out, node, mDepth);
100 0 : out << "vector swizzle";
101 0 : return true;
102 : }
103 :
104 0 : bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
105 : {
106 0 : TInfoSinkBase& out = sink;
107 :
108 0 : OutputTreeText(out, node, mDepth);
109 :
110 0 : switch (node->getOp())
111 : {
112 : case EOpComma:
113 0 : out << "comma";
114 0 : break;
115 : case EOpAssign:
116 0 : out << "move second child to first child";
117 0 : break;
118 : case EOpInitialize:
119 0 : out << "initialize first child with second child";
120 0 : break;
121 : case EOpAddAssign:
122 0 : out << "add second child into first child";
123 0 : break;
124 : case EOpSubAssign:
125 0 : out << "subtract second child into first child";
126 0 : break;
127 : case EOpMulAssign:
128 0 : out << "multiply second child into first child";
129 0 : break;
130 : case EOpVectorTimesMatrixAssign:
131 0 : out << "matrix mult second child into first child";
132 0 : break;
133 : case EOpVectorTimesScalarAssign:
134 0 : out << "vector scale second child into first child";
135 0 : break;
136 : case EOpMatrixTimesScalarAssign:
137 0 : out << "matrix scale second child into first child";
138 0 : break;
139 : case EOpMatrixTimesMatrixAssign:
140 0 : out << "matrix mult second child into first child";
141 0 : break;
142 : case EOpDivAssign:
143 0 : out << "divide second child into first child";
144 0 : break;
145 : case EOpIModAssign:
146 0 : out << "modulo second child into first child";
147 0 : break;
148 : case EOpBitShiftLeftAssign:
149 0 : out << "bit-wise shift first child left by second child";
150 0 : break;
151 : case EOpBitShiftRightAssign:
152 0 : out << "bit-wise shift first child right by second child";
153 0 : break;
154 : case EOpBitwiseAndAssign:
155 0 : out << "bit-wise and second child into first child";
156 0 : break;
157 : case EOpBitwiseXorAssign:
158 0 : out << "bit-wise xor second child into first child";
159 0 : break;
160 : case EOpBitwiseOrAssign:
161 0 : out << "bit-wise or second child into first child";
162 0 : break;
163 :
164 : case EOpIndexDirect:
165 0 : out << "direct index";
166 0 : break;
167 : case EOpIndexIndirect:
168 0 : out << "indirect index";
169 0 : break;
170 : case EOpIndexDirectStruct:
171 0 : out << "direct index for structure";
172 0 : break;
173 : case EOpIndexDirectInterfaceBlock:
174 0 : out << "direct index for interface block";
175 0 : break;
176 :
177 : case EOpAdd:
178 0 : out << "add";
179 0 : break;
180 : case EOpSub:
181 0 : out << "subtract";
182 0 : break;
183 : case EOpMul:
184 0 : out << "component-wise multiply";
185 0 : break;
186 : case EOpDiv:
187 0 : out << "divide";
188 0 : break;
189 : case EOpIMod:
190 0 : out << "modulo";
191 0 : break;
192 : case EOpBitShiftLeft:
193 0 : out << "bit-wise shift left";
194 0 : break;
195 : case EOpBitShiftRight:
196 0 : out << "bit-wise shift right";
197 0 : break;
198 : case EOpBitwiseAnd:
199 0 : out << "bit-wise and";
200 0 : break;
201 : case EOpBitwiseXor:
202 0 : out << "bit-wise xor";
203 0 : break;
204 : case EOpBitwiseOr:
205 0 : out << "bit-wise or";
206 0 : break;
207 :
208 : case EOpEqual:
209 0 : out << "Compare Equal";
210 0 : break;
211 : case EOpNotEqual:
212 0 : out << "Compare Not Equal";
213 0 : break;
214 : case EOpLessThan:
215 0 : out << "Compare Less Than";
216 0 : break;
217 : case EOpGreaterThan:
218 0 : out << "Compare Greater Than";
219 0 : break;
220 : case EOpLessThanEqual:
221 0 : out << "Compare Less Than or Equal";
222 0 : break;
223 : case EOpGreaterThanEqual:
224 0 : out << "Compare Greater Than or Equal";
225 0 : break;
226 :
227 : case EOpVectorTimesScalar:
228 0 : out << "vector-scale";
229 0 : break;
230 : case EOpVectorTimesMatrix:
231 0 : out << "vector-times-matrix";
232 0 : break;
233 : case EOpMatrixTimesVector:
234 0 : out << "matrix-times-vector";
235 0 : break;
236 : case EOpMatrixTimesScalar:
237 0 : out << "matrix-scale";
238 0 : break;
239 : case EOpMatrixTimesMatrix:
240 0 : out << "matrix-multiply";
241 0 : break;
242 :
243 : case EOpLogicalOr:
244 0 : out << "logical-or";
245 0 : break;
246 : case EOpLogicalXor:
247 0 : out << "logical-xor";
248 0 : break;
249 : case EOpLogicalAnd:
250 0 : out << "logical-and";
251 0 : break;
252 : default:
253 0 : out << "<unknown op>";
254 : }
255 :
256 0 : out << " (" << node->getCompleteString() << ")";
257 :
258 0 : out << "\n";
259 :
260 : // Special handling for direct indexes. Because constant
261 : // unions are not aware they are struct indexes, treat them
262 : // here where we have that contextual knowledge.
263 0 : if (node->getOp() == EOpIndexDirectStruct ||
264 0 : node->getOp() == EOpIndexDirectInterfaceBlock)
265 : {
266 0 : mDepth++;
267 0 : node->getLeft()->traverse(this);
268 0 : mDepth--;
269 :
270 0 : TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
271 0 : ASSERT(intermConstantUnion);
272 :
273 0 : OutputTreeText(out, intermConstantUnion, mDepth + 1);
274 :
275 : // The following code finds the field name from the constant union
276 0 : const TConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
277 0 : const TStructure *structure = node->getLeft()->getType().getStruct();
278 0 : const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
279 0 : ASSERT(structure || interfaceBlock);
280 :
281 0 : const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
282 :
283 0 : const TField *field = fields[constantUnion->getIConst()];
284 :
285 0 : out << constantUnion->getIConst() << " (field '" << field->name() << "')";
286 :
287 0 : return false;
288 : }
289 :
290 0 : return true;
291 : }
292 :
293 0 : bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
294 : {
295 0 : TInfoSinkBase& out = sink;
296 :
297 0 : OutputTreeText(out, node, mDepth);
298 :
299 0 : switch (node->getOp())
300 : {
301 0 : case EOpNegative: out << "Negate value"; break;
302 0 : case EOpPositive: out << "Positive sign"; break;
303 : case EOpVectorLogicalNot:
304 0 : case EOpLogicalNot: out << "Negate conditional"; break;
305 0 : case EOpBitwiseNot: out << "bit-wise not"; break;
306 :
307 0 : case EOpPostIncrement: out << "Post-Increment"; break;
308 0 : case EOpPostDecrement: out << "Post-Decrement"; break;
309 0 : case EOpPreIncrement: out << "Pre-Increment"; break;
310 0 : case EOpPreDecrement: out << "Pre-Decrement"; break;
311 :
312 0 : case EOpRadians: out << "radians"; break;
313 0 : case EOpDegrees: out << "degrees"; break;
314 0 : case EOpSin: out << "sine"; break;
315 0 : case EOpCos: out << "cosine"; break;
316 0 : case EOpTan: out << "tangent"; break;
317 0 : case EOpAsin: out << "arc sine"; break;
318 0 : case EOpAcos: out << "arc cosine"; break;
319 0 : case EOpAtan: out << "arc tangent"; break;
320 :
321 0 : case EOpSinh: out << "hyperbolic sine"; break;
322 0 : case EOpCosh: out << "hyperbolic cosine"; break;
323 0 : case EOpTanh: out << "hyperbolic tangent"; break;
324 0 : case EOpAsinh: out << "arc hyperbolic sine"; break;
325 0 : case EOpAcosh: out << "arc hyperbolic cosine"; break;
326 0 : case EOpAtanh: out << "arc hyperbolic tangent"; break;
327 :
328 0 : case EOpExp: out << "exp"; break;
329 0 : case EOpLog: out << "log"; break;
330 0 : case EOpExp2: out << "exp2"; break;
331 0 : case EOpLog2: out << "log2"; break;
332 0 : case EOpSqrt: out << "sqrt"; break;
333 0 : case EOpInverseSqrt: out << "inverse sqrt"; break;
334 :
335 0 : case EOpAbs: out << "Absolute value"; break;
336 0 : case EOpSign: out << "Sign"; break;
337 0 : case EOpFloor: out << "Floor"; break;
338 0 : case EOpTrunc: out << "Truncate"; break;
339 0 : case EOpRound: out << "Round"; break;
340 0 : case EOpRoundEven: out << "Round half even"; break;
341 0 : case EOpCeil: out << "Ceiling"; break;
342 0 : case EOpFract: out << "Fraction"; break;
343 0 : case EOpIsNan: out << "Is not a number"; break;
344 0 : case EOpIsInf: out << "Is infinity"; break;
345 :
346 0 : case EOpFloatBitsToInt: out << "float bits to int"; break;
347 0 : case EOpFloatBitsToUint: out << "float bits to uint"; break;
348 0 : case EOpIntBitsToFloat: out << "int bits to float"; break;
349 0 : case EOpUintBitsToFloat: out << "uint bits to float"; break;
350 :
351 0 : case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break;
352 0 : case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break;
353 0 : case EOpPackHalf2x16: out << "pack half 2x16"; break;
354 :
355 0 : case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break;
356 0 : case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break;
357 0 : case EOpUnpackHalf2x16: out << "unpack half 2x16"; break;
358 :
359 0 : case EOpLength: out << "length"; break;
360 0 : case EOpNormalize: out << "normalize"; break;
361 : // case EOpDPdx: out << "dPdx"; break;
362 : // case EOpDPdy: out << "dPdy"; break;
363 : // case EOpFwidth: out << "fwidth"; break;
364 :
365 0 : case EOpDeterminant: out << "determinant"; break;
366 0 : case EOpTranspose: out << "transpose"; break;
367 0 : case EOpInverse: out << "inverse"; break;
368 :
369 0 : case EOpAny: out << "any"; break;
370 0 : case EOpAll: out << "all"; break;
371 :
372 : default:
373 0 : out.prefix(EPrefixError);
374 0 : out << "Bad unary op";
375 : }
376 :
377 0 : out << " (" << node->getCompleteString() << ")";
378 :
379 0 : out << "\n";
380 :
381 0 : return true;
382 : }
383 :
384 0 : bool TOutputTraverser::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
385 : {
386 0 : TInfoSinkBase &out = sink;
387 0 : OutputTreeText(out, node, mDepth);
388 0 : OutputFunction(out, "Function Definition", node->getFunctionSymbolInfo());
389 0 : out << "\n";
390 0 : return true;
391 : }
392 :
393 0 : bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
394 : {
395 0 : TInfoSinkBase &out = sink;
396 :
397 0 : OutputTreeText(out, node, mDepth);
398 :
399 0 : if (node->getOp() == EOpNull)
400 : {
401 0 : out.prefix(EPrefixError);
402 0 : out << "node is still EOpNull!\n";
403 0 : return true;
404 : }
405 :
406 :
407 0 : switch (node->getOp())
408 : {
409 : case EOpFunctionCall:
410 0 : OutputFunction(out, "Function Call", node->getFunctionSymbolInfo());
411 0 : break;
412 0 : case EOpParameters: out << "Function Parameters: "; break;
413 : case EOpPrototype:
414 0 : OutputFunction(out, "Function Prototype", node->getFunctionSymbolInfo());
415 0 : break;
416 :
417 0 : case EOpConstructFloat: out << "Construct float"; break;
418 0 : case EOpConstructVec2: out << "Construct vec2"; break;
419 0 : case EOpConstructVec3: out << "Construct vec3"; break;
420 0 : case EOpConstructVec4: out << "Construct vec4"; break;
421 0 : case EOpConstructBool: out << "Construct bool"; break;
422 0 : case EOpConstructBVec2: out << "Construct bvec2"; break;
423 0 : case EOpConstructBVec3: out << "Construct bvec3"; break;
424 0 : case EOpConstructBVec4: out << "Construct bvec4"; break;
425 0 : case EOpConstructInt: out << "Construct int"; break;
426 0 : case EOpConstructIVec2: out << "Construct ivec2"; break;
427 0 : case EOpConstructIVec3: out << "Construct ivec3"; break;
428 0 : case EOpConstructIVec4: out << "Construct ivec4"; break;
429 0 : case EOpConstructUInt: out << "Construct uint"; break;
430 0 : case EOpConstructUVec2: out << "Construct uvec2"; break;
431 0 : case EOpConstructUVec3: out << "Construct uvec3"; break;
432 0 : case EOpConstructUVec4: out << "Construct uvec4"; break;
433 0 : case EOpConstructMat2: out << "Construct mat2"; break;
434 0 : case EOpConstructMat2x3: out << "Construct mat2x3"; break;
435 0 : case EOpConstructMat2x4: out << "Construct mat2x4"; break;
436 0 : case EOpConstructMat3x2: out << "Construct mat3x2"; break;
437 0 : case EOpConstructMat3: out << "Construct mat3"; break;
438 0 : case EOpConstructMat3x4: out << "Construct mat3x4"; break;
439 0 : case EOpConstructMat4x2: out << "Construct mat4x2"; break;
440 0 : case EOpConstructMat4x3: out << "Construct mat4x3"; break;
441 0 : case EOpConstructMat4: out << "Construct mat4"; break;
442 0 : case EOpConstructStruct: out << "Construct structure"; break;
443 :
444 0 : case EOpLessThan: out << "Compare Less Than"; break;
445 0 : case EOpGreaterThan: out << "Compare Greater Than"; break;
446 0 : case EOpLessThanEqual: out << "Compare Less Than or Equal"; break;
447 0 : case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
448 0 : case EOpVectorEqual: out << "Equal"; break;
449 0 : case EOpVectorNotEqual: out << "NotEqual"; break;
450 :
451 0 : case EOpMod: out << "mod"; break;
452 0 : case EOpModf: out << "modf"; break;
453 0 : case EOpPow: out << "pow"; break;
454 :
455 0 : case EOpAtan: out << "arc tangent"; break;
456 :
457 0 : case EOpMin: out << "min"; break;
458 0 : case EOpMax: out << "max"; break;
459 0 : case EOpClamp: out << "clamp"; break;
460 0 : case EOpMix: out << "mix"; break;
461 0 : case EOpStep: out << "step"; break;
462 0 : case EOpSmoothStep: out << "smoothstep"; break;
463 :
464 0 : case EOpDistance: out << "distance"; break;
465 0 : case EOpDot: out << "dot-product"; break;
466 0 : case EOpCross: out << "cross-product"; break;
467 0 : case EOpFaceForward: out << "face-forward"; break;
468 0 : case EOpReflect: out << "reflect"; break;
469 0 : case EOpRefract: out << "refract"; break;
470 0 : case EOpMul: out << "component-wise multiply"; break;
471 :
472 0 : case EOpOuterProduct: out << "outer product"; break;
473 :
474 0 : case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
475 :
476 : default:
477 0 : out.prefix(EPrefixError);
478 0 : out << "Bad aggregation op";
479 : }
480 :
481 0 : if (node->getOp() != EOpParameters)
482 0 : out << " (" << node->getCompleteString() << ")";
483 :
484 0 : out << "\n";
485 :
486 0 : return true;
487 : }
488 :
489 0 : bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
490 : {
491 0 : TInfoSinkBase &out = sink;
492 :
493 0 : OutputTreeText(out, node, mDepth);
494 0 : out << "Code block\n";
495 :
496 0 : return true;
497 : }
498 :
499 0 : bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
500 : {
501 0 : TInfoSinkBase &out = sink;
502 :
503 0 : OutputTreeText(out, node, mDepth);
504 0 : out << "Declaration\n";
505 :
506 0 : return true;
507 : }
508 :
509 0 : bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
510 : {
511 0 : TInfoSinkBase &out = sink;
512 :
513 0 : OutputTreeText(out, node, mDepth);
514 :
515 0 : out << "Ternary selection";
516 0 : out << " (" << node->getCompleteString() << ")\n";
517 :
518 0 : ++mDepth;
519 :
520 0 : OutputTreeText(sink, node, mDepth);
521 0 : out << "Condition\n";
522 0 : node->getCondition()->traverse(this);
523 :
524 0 : OutputTreeText(sink, node, mDepth);
525 0 : if (node->getTrueExpression())
526 : {
527 0 : out << "true case\n";
528 0 : node->getTrueExpression()->traverse(this);
529 : }
530 0 : if (node->getFalseExpression())
531 : {
532 0 : OutputTreeText(sink, node, mDepth);
533 0 : out << "false case\n";
534 0 : node->getFalseExpression()->traverse(this);
535 : }
536 :
537 0 : --mDepth;
538 :
539 0 : return false;
540 : }
541 :
542 0 : bool TOutputTraverser::visitIfElse(Visit visit, TIntermIfElse *node)
543 : {
544 0 : TInfoSinkBase &out = sink;
545 :
546 0 : OutputTreeText(out, node, mDepth);
547 :
548 0 : out << "If test\n";
549 :
550 0 : ++mDepth;
551 :
552 0 : OutputTreeText(sink, node, mDepth);
553 0 : out << "Condition\n";
554 0 : node->getCondition()->traverse(this);
555 :
556 0 : OutputTreeText(sink, node, mDepth);
557 0 : if (node->getTrueBlock())
558 : {
559 0 : out << "true case\n";
560 0 : node->getTrueBlock()->traverse(this);
561 : }
562 : else
563 : {
564 0 : out << "true case is null\n";
565 : }
566 :
567 0 : if (node->getFalseBlock())
568 : {
569 0 : OutputTreeText(sink, node, mDepth);
570 0 : out << "false case\n";
571 0 : node->getFalseBlock()->traverse(this);
572 : }
573 :
574 0 : --mDepth;
575 :
576 0 : return false;
577 : }
578 :
579 0 : bool TOutputTraverser::visitSwitch(Visit visit, TIntermSwitch *node)
580 : {
581 0 : TInfoSinkBase &out = sink;
582 :
583 0 : OutputTreeText(out, node, mDepth);
584 :
585 0 : out << "Switch\n";
586 :
587 0 : return true;
588 : }
589 :
590 0 : bool TOutputTraverser::visitCase(Visit visit, TIntermCase *node)
591 : {
592 0 : TInfoSinkBase &out = sink;
593 :
594 0 : OutputTreeText(out, node, mDepth);
595 :
596 0 : if (node->getCondition() == nullptr)
597 : {
598 0 : out << "Default\n";
599 : }
600 : else
601 : {
602 0 : out << "Case\n";
603 : }
604 :
605 0 : return true;
606 : }
607 :
608 0 : void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node)
609 : {
610 0 : TInfoSinkBase &out = sink;
611 :
612 0 : size_t size = node->getType().getObjectSize();
613 :
614 0 : for (size_t i = 0; i < size; i++)
615 : {
616 0 : OutputTreeText(out, node, mDepth);
617 0 : switch (node->getUnionArrayPointer()[i].getType())
618 : {
619 : case EbtBool:
620 0 : if (node->getUnionArrayPointer()[i].getBConst())
621 0 : out << "true";
622 : else
623 0 : out << "false";
624 :
625 0 : out << " (" << "const bool" << ")";
626 0 : out << "\n";
627 0 : break;
628 : case EbtFloat:
629 0 : out << node->getUnionArrayPointer()[i].getFConst();
630 0 : out << " (const float)\n";
631 0 : break;
632 : case EbtInt:
633 0 : out << node->getUnionArrayPointer()[i].getIConst();
634 0 : out << " (const int)\n";
635 0 : break;
636 : case EbtUInt:
637 0 : out << node->getUnionArrayPointer()[i].getUConst();
638 0 : out << " (const uint)\n";
639 0 : break;
640 : default:
641 0 : out.message(EPrefixInternalError, node->getLine(), "Unknown constant");
642 0 : break;
643 : }
644 : }
645 0 : }
646 :
647 0 : bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node)
648 : {
649 0 : TInfoSinkBase &out = sink;
650 :
651 0 : OutputTreeText(out, node, mDepth);
652 :
653 0 : out << "Loop with condition ";
654 0 : if (node->getType() == ELoopDoWhile)
655 0 : out << "not ";
656 0 : out << "tested first\n";
657 :
658 0 : ++mDepth;
659 :
660 0 : OutputTreeText(sink, node, mDepth);
661 0 : if (node->getCondition())
662 : {
663 0 : out << "Loop Condition\n";
664 0 : node->getCondition()->traverse(this);
665 : }
666 : else
667 : {
668 0 : out << "No loop condition\n";
669 : }
670 :
671 0 : OutputTreeText(sink, node, mDepth);
672 0 : if (node->getBody())
673 : {
674 0 : out << "Loop Body\n";
675 0 : node->getBody()->traverse(this);
676 : }
677 : else
678 : {
679 0 : out << "No loop body\n";
680 : }
681 :
682 0 : if (node->getExpression())
683 : {
684 0 : OutputTreeText(sink, node, mDepth);
685 0 : out << "Loop Terminal Expression\n";
686 0 : node->getExpression()->traverse(this);
687 : }
688 :
689 0 : --mDepth;
690 :
691 0 : return false;
692 : }
693 :
694 0 : bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
695 : {
696 0 : TInfoSinkBase &out = sink;
697 :
698 0 : OutputTreeText(out, node, mDepth);
699 :
700 0 : switch (node->getFlowOp())
701 : {
702 0 : case EOpKill: out << "Branch: Kill"; break;
703 0 : case EOpBreak: out << "Branch: Break"; break;
704 0 : case EOpContinue: out << "Branch: Continue"; break;
705 0 : case EOpReturn: out << "Branch: Return"; break;
706 0 : default: out << "Branch: Unknown Branch"; break;
707 : }
708 :
709 0 : if (node->getExpression())
710 : {
711 0 : out << " with expression\n";
712 0 : ++mDepth;
713 0 : node->getExpression()->traverse(this);
714 0 : --mDepth;
715 : }
716 : else
717 : {
718 0 : out << "\n";
719 : }
720 :
721 0 : return false;
722 : }
723 :
724 : //
725 : // This function is the one to call externally to start the traversal.
726 : // Individual functions can be initialized to 0 to skip processing of that
727 : // type of node. Its children will still be processed.
728 : //
729 0 : void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
730 : {
731 0 : TOutputTraverser it(infoSink);
732 :
733 0 : ASSERT(root);
734 :
735 0 : root->traverse(&it);
736 0 : }
737 :
738 : } // namespace sh
|