1a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
2a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Use of this source code is governed by a BSD-style license that can be
4a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// found in the LICENSE file.
5a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
6a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
7a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block#include "compiler/localintermediate.h"
8a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
9a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
10a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Two purposes:
11a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// 1.  Show an example of how to iterate tree.  Functions can
12a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//     also directly call Traverse() on children themselves to
13a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//     have finer grained control over the process than shown here.
14a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//     See the last function for how to get started.
15a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// 2.  Print out a text based description of the tree.
16a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
17a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
18a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
19a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Use this class to carry along data from node to node in
20a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// the traversal
21a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
22a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockclass TOutputTraverser : public TIntermTraverser {
23a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockpublic:
24ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TOutputTraverser(TInfoSinkBase& i) : sink(i) { }
25ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& sink;
26a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
27a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockprotected:
28a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    void visitSymbol(TIntermSymbol*);
29a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    void visitConstantUnion(TIntermConstantUnion*);
30a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitBinary(Visit visit, TIntermBinary*);
31a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitUnary(Visit visit, TIntermUnary*);
32a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitSelection(Visit visit, TIntermSelection*);
33a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitAggregate(Visit visit, TIntermAggregate*);
34a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitLoop(Visit visit, TIntermLoop*);
35a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    bool visitBranch(Visit visit, TIntermBranch*);
36a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block};
37a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
38a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve BlockTString TType::getCompleteString() const
39a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
40a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    TStringStream stream;
41a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
42a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (qualifier != EvqTemporary && qualifier != EvqGlobal)
43a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        stream << getQualifierString() << " " << getPrecisionString() << " ";
44a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (array)
45a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        stream << "array of ";
46a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (matrix)
47a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        stream << size << "X" << size << " matrix of ";
48a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    else if (size > 1)
49a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        stream << size << "-component vector of ";
50a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
51a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    stream << getBasicString();
52a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return stream.str();
53a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
54a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
55a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
56a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Helper functions for printing, not part of traversing.
57a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
58a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
59ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdochvoid OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth)
60a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
61a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    int i;
62a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
63ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    sink.location(node->getLine());
64a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
65a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    for (i = 0; i < depth; ++i)
66ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        sink << "  ";
67a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
68a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
69a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
70a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// The rest of the file are the traversal functions.  The last one
71a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// is the one that starts the traversal.
72a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
73a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Return true from interior nodes to have the external traversal
74a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// continue on to children.  If you process children yourself,
75a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// return false.
76a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
77a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
78a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputTraverser::visitSymbol(TIntermSymbol* node)
79a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
80ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    OutputTreeText(sink, node, depth);
81a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
82ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    sink << "'" << node->getSymbol() << "' ";
83ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    sink << "(" << node->getCompleteString() << ")\n";
84a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
85a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
86a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
87a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
88ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
89a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
90a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    OutputTreeText(out, node, depth);
91a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
92a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getOp()) {
93ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAssign:                   out << "move second child to first child";           break;
94ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpInitialize:               out << "initialize first child with second child";   break;
95ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAddAssign:                out << "add second child into first child";          break;
96ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSubAssign:                out << "subtract second child into first child";     break;
97ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMulAssign:                out << "multiply second child into first child";     break;
98ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorTimesMatrixAssign:  out << "matrix mult second child into first child";  break;
99ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorTimesScalarAssign:  out << "vector scale second child into first child"; break;
100ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMatrixTimesScalarAssign:  out << "matrix scale second child into first child"; break;
101ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMatrixTimesMatrixAssign:  out << "matrix mult second child into first child"; break;
102ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDivAssign:                out << "divide second child into first child";       break;
103ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpIndexDirect:   out << "direct index";   break;
104ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpIndexIndirect: out << "indirect index"; break;
105ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpIndexDirectStruct:   out << "direct index for structure";   break;
106ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorSwizzle: out << "vector swizzle"; break;
107ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
108ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAdd:    out << "add";                     break;
109ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSub:    out << "subtract";                break;
110ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMul:    out << "component-wise multiply"; break;
111ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDiv:    out << "divide";                  break;
112ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpEqual:            out << "Compare Equal";                 break;
113ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpNotEqual:         out << "Compare Not Equal";             break;
114ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLessThan:         out << "Compare Less Than";             break;
115ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpGreaterThan:      out << "Compare Greater Than";          break;
116ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
117ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
118ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
119ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorTimesScalar: out << "vector-scale";          break;
120ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorTimesMatrix: out << "vector-times-matrix";   break;
121ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMatrixTimesVector: out << "matrix-times-vector";   break;
122ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMatrixTimesScalar: out << "matrix-scale";          break;
123ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMatrixTimesMatrix: out << "matrix-multiply";       break;
124ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
125ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLogicalOr:  out << "logical-or";   break;
126ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLogicalXor: out << "logical-xor"; break;
127ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLogicalAnd: out << "logical-and"; break;
128ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        default: out << "<unknown op>";
129a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
130a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
131ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << " (" << node->getCompleteString() << ")";
132a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
133ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "\n";
134a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
135a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
136a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
137a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
138a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node)
139a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
140ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
141a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
142a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    OutputTreeText(out, node, depth);
143a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
144a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getOp()) {
145ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpNegative:       out << "Negate value";         break;
146a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        case EOpVectorLogicalNot:
147ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLogicalNot:     out << "Negate conditional";   break;
148ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
149ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpPostIncrement:  out << "Post-Increment";       break;
150ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpPostDecrement:  out << "Post-Decrement";       break;
151ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpPreIncrement:   out << "Pre-Increment";        break;
152ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpPreDecrement:   out << "Pre-Decrement";        break;
153ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
154ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConvIntToBool:  out << "Convert int to bool";  break;
155ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConvFloatToBool:out << "Convert float to bool";break;
156ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConvBoolToFloat:out << "Convert bool to float";break;
157ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConvIntToFloat: out << "Convert int to float"; break;
158ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConvFloatToInt: out << "Convert float to int"; break;
159ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConvBoolToInt:  out << "Convert bool to int";  break;
160ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
161ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpRadians:        out << "radians";              break;
162ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDegrees:        out << "degrees";              break;
163ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSin:            out << "sine";                 break;
164ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpCos:            out << "cosine";               break;
165ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpTan:            out << "tangent";              break;
166ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAsin:           out << "arc sine";             break;
167ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAcos:           out << "arc cosine";           break;
168ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAtan:           out << "arc tangent";          break;
169ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
170ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpExp:            out << "exp";                  break;
171ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLog:            out << "log";                  break;
172ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpExp2:           out << "exp2";                 break;
173ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLog2:           out << "log2";                 break;
174ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSqrt:           out << "sqrt";                 break;
175ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpInverseSqrt:    out << "inverse sqrt";         break;
176ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
177ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAbs:            out << "Absolute value";       break;
178ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSign:           out << "Sign";                 break;
179ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpFloor:          out << "Floor";                break;
180ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpCeil:           out << "Ceiling";              break;
181ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpFract:          out << "Fraction";             break;
182ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
183ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLength:         out << "length";               break;
184ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpNormalize:      out << "normalize";            break;
185ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            //	case EOpDPdx:           out << "dPdx";                 break;
186ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            //	case EOpDPdy:           out << "dPdy";                 break;
187ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch            //	case EOpFwidth:         out << "fwidth";               break;
188ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
189ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAny:            out << "any";                  break;
190ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAll:            out << "all";                  break;
191ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
192ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        default: out.message(EPrefixError, "Bad unary op");
193a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
194a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
195ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << " (" << node->getCompleteString() << ")";
196a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
197ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "\n";
198a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
199a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
200a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
201a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
202a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
203a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
204ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
205a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
206a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->getOp() == EOpNull) {
207ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out.message(EPrefixError, "node is still EOpNull!");
208a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return true;
209a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
210a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
211a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    OutputTreeText(out, node, depth);
212a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
213a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getOp()) {
214ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSequence:      out << "Sequence\n"; return true;
215ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpComma:         out << "Comma\n"; return true;
216ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpFunction:      out << "Function Definition: " << node->getName(); break;
217ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpFunctionCall:  out << "Function Call: " << node->getName(); break;
218ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpParameters:    out << "Function Parameters: ";              break;
219ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
220ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructFloat: out << "Construct float"; break;
221ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructVec2:  out << "Construct vec2";  break;
222ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructVec3:  out << "Construct vec3";  break;
223ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructVec4:  out << "Construct vec4";  break;
224ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructBool:  out << "Construct bool";  break;
225ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructBVec2: out << "Construct bvec2"; break;
226ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructBVec3: out << "Construct bvec3"; break;
227ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructBVec4: out << "Construct bvec4"; break;
228ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructInt:   out << "Construct int";   break;
229ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructIVec2: out << "Construct ivec2"; break;
230ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructIVec3: out << "Construct ivec3"; break;
231ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructIVec4: out << "Construct ivec4"; break;
232ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructMat2:  out << "Construct mat2";  break;
233ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructMat3:  out << "Construct mat3";  break;
234ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructMat4:  out << "Construct mat4";  break;
235ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpConstructStruct:  out << "Construct structure";  break;
236ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
237ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLessThan:         out << "Compare Less Than";             break;
238ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpGreaterThan:      out << "Compare Greater Than";          break;
239ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpLessThanEqual:    out << "Compare Less Than or Equal";    break;
240ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break;
241ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorEqual:      out << "Equal";                         break;
242ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpVectorNotEqual:   out << "NotEqual";                      break;
243ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
244ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMod:           out << "mod";         break;
245ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpPow:           out << "pow";         break;
246ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
247ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpAtan:          out << "arc tangent"; break;
248ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
249ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMin:           out << "min";         break;
250ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMax:           out << "max";         break;
251ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpClamp:         out << "clamp";       break;
252ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMix:           out << "mix";         break;
253ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpStep:          out << "step";        break;
254ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpSmoothStep:    out << "smoothstep";  break;
255ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
256ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDistance:      out << "distance";                break;
257ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpDot:           out << "dot-product";             break;
258ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpCross:         out << "cross-product";           break;
259ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpFaceForward:   out << "face-forward";            break;
260ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpReflect:       out << "reflect";                 break;
261ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpRefract:       out << "refract";                 break;
262ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpMul:           out << "component-wise multiply"; break;
263ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch
264ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        default: out.message(EPrefixError, "Bad aggregation op");
265a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
266a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
267a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
268ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << " (" << node->getCompleteString() << ")";
269a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
270ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "\n";
271a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
272a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return true;
273a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
274a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
275a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node)
276a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
277ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
278a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
279a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    OutputTreeText(out, node, depth);
280a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
281ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "Test condition and select";
282ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << " (" << node->getCompleteString() << ")\n";
283a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
284a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    ++depth;
285a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
286ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    OutputTreeText(sink, node, depth);
287ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "Condition\n";
288a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    node->getCondition()->traverse(this);
289a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
290ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    OutputTreeText(sink, node, depth);
291a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->getTrueBlock()) {
292ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "true case\n";
293a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getTrueBlock()->traverse(this);
294a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    } else
295ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "true case is null\n";
296a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
297a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->getFalseBlock()) {
298ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        OutputTreeText(sink, node, depth);
299ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "false case\n";
300a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getFalseBlock()->traverse(this);
301a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
302a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
303a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    --depth;
304a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
305a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return false;
306a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
307a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
308a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
309a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
310ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
311a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
312a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    int size = node->getType().getObjectSize();
313a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
314a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    for (int i = 0; i < size; i++) {
315a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        OutputTreeText(out, node, depth);
316a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        switch (node->getUnionArrayPointer()[i].getType()) {
317a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            case EbtBool:
318a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                if (node->getUnionArrayPointer()[i].getBConst())
319ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                    out << "true";
320a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                else
321ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                    out << "false";
322a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
323ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out << " (" << "const bool" << ")";
324ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out << "\n";
325a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                break;
326a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            case EbtFloat:
327ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out << node->getUnionArrayPointer()[i].getFConst();
328ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out << " (const float)\n";
329a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                break;
330a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            case EbtInt:
331ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out << node->getUnionArrayPointer()[i].getIConst();
332ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out << " (const int)\n";
333a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                break;
334a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block            default:
335ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch                out.message(EPrefixInternalError, "Unknown constant", node->getLine());
336a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block                break;
337a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        }
338a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
339a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
340a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
341a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node)
342a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
343ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
344a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
345a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    OutputTreeText(out, node, depth);
346a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
347ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "Loop with condition ";
348ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (node->getType() == ELoopDoWhile)
349ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "not ";
350ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    out << "tested first\n";
351a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
352a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    ++depth;
353a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
354ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    OutputTreeText(sink, node, depth);
355ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (node->getCondition()) {
356ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "Loop Condition\n";
357ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        node->getCondition()->traverse(this);
358a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    } else
359ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "No loop condition\n";
360a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
361ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    OutputTreeText(sink, node, depth);
362a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->getBody()) {
363ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "Loop Body\n";
364a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getBody()->traverse(this);
365a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    } else
366ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "No loop body\n";
367a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
368ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    if (node->getExpression()) {
369ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        OutputTreeText(sink, node, depth);
370ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "Loop Terminal Expression\n";
371ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        node->getExpression()->traverse(this);
372a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
373a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
374a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    --depth;
375a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
376a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return false;
377a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
378a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
379a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockbool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node)
380a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
381ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TInfoSinkBase& out = sink;
382a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
383a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    OutputTreeText(out, node, depth);
384a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
385a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    switch (node->getFlowOp()) {
386ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpKill:      out << "Branch: Kill";           break;
387ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpBreak:     out << "Branch: Break";          break;
388ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpContinue:  out << "Branch: Continue";       break;
389ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        case EOpReturn:    out << "Branch: Return";         break;
390ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        default:           out << "Branch: Unknown Branch"; break;
391a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    }
392a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
393a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (node->getExpression()) {
394ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << " with expression\n";
395a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        ++depth;
396a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        node->getExpression()->traverse(this);
397a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        --depth;
398a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    } else
399ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch        out << "\n";
400a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
401a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    return false;
402a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
403a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
404a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
405a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// This function is the one to call externally to start the traversal.
406a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// Individual functions can be initialized to 0 to skip processing of that
407a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block// type of node.  It's children will still be processed.
408a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block//
409a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Blockvoid TIntermediate::outputTree(TIntermNode* root)
410a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block{
411a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    if (root == 0)
412a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block        return;
413a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
414ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    TOutputTraverser it(infoSink.info);
415a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block
416a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block    root->traverse(&it);
417a9bfd6c4a32dfd9cc032cb67c6ccb8d09c16f579Steve Block}
418