AST: dump attributes along with control flow.
[platform/upstream/glslang.git] / glslang / MachineIndependent / intermOut.cpp
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2016 LunarG, Inc.
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //    Redistributions of source code must retain the above copyright
12 //    notice, this list of conditions and the following disclaimer.
13 //
14 //    Redistributions in binary form must reproduce the above
15 //    copyright notice, this list of conditions and the following
16 //    disclaimer in the documentation and/or other materials provided
17 //    with the distribution.
18 //
19 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20 //    contributors may be used to endorse or promote products derived
21 //    from this software without specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 // POSSIBILITY OF SUCH DAMAGE.
35 //
36
37 #include "localintermediate.h"
38 #include "../Include/InfoSink.h"
39
40 #ifdef _MSC_VER
41 #include <cfloat>
42 #else
43 #include <cmath>
44 #endif
45
46 namespace {
47
48 bool IsInfinity(double x) {
49 #ifdef _MSC_VER
50     switch (_fpclass(x)) {
51     case _FPCLASS_NINF:
52     case _FPCLASS_PINF:
53         return true;
54     default:
55         return false;
56     }
57 #else
58     return std::isinf(x);
59 #endif
60 }
61
62 bool IsNan(double x) {
63 #ifdef _MSC_VER
64     switch (_fpclass(x)) {
65     case _FPCLASS_SNAN:
66     case _FPCLASS_QNAN:
67         return true;
68     default:
69         return false;
70     }
71 #else
72   return std::isnan(x);
73 #endif
74 }
75
76 }
77
78 namespace glslang {
79
80 //
81 // Two purposes:
82 // 1.  Show an example of how to iterate tree.  Functions can
83 //     also directly call Traverse() on children themselves to
84 //     have finer grained control over the process than shown here.
85 //     See the last function for how to get started.
86 // 2.  Print out a text based description of the tree.
87 //
88
89 //
90 // Use this class to carry along data from node to node in
91 // the traversal
92 //
93 class TOutputTraverser : public TIntermTraverser {
94 public:
95     TOutputTraverser(TInfoSink& i) : infoSink(i) { }
96
97     virtual bool visitBinary(TVisit, TIntermBinary* node);
98     virtual bool visitUnary(TVisit, TIntermUnary* node);
99     virtual bool visitAggregate(TVisit, TIntermAggregate* node);
100     virtual bool visitSelection(TVisit, TIntermSelection* node);
101     virtual void visitConstantUnion(TIntermConstantUnion* node);
102     virtual void visitSymbol(TIntermSymbol* node);
103     virtual bool visitLoop(TVisit, TIntermLoop* node);
104     virtual bool visitBranch(TVisit, TIntermBranch* node);
105     virtual bool visitSwitch(TVisit, TIntermSwitch* node);
106
107     TInfoSink& infoSink;
108 protected:
109     TOutputTraverser(TOutputTraverser&);
110     TOutputTraverser& operator=(TOutputTraverser&);
111 };
112
113 //
114 // Helper functions for printing, not part of traversing.
115 //
116
117 static void OutputTreeText(TInfoSink& infoSink, const TIntermNode* node, const int depth)
118 {
119     int i;
120
121     infoSink.debug << node->getLoc().string << ":";
122     if (node->getLoc().line)
123         infoSink.debug << node->getLoc().line;
124     else
125         infoSink.debug << "? ";
126
127     for (i = 0; i < depth; ++i)
128         infoSink.debug << "  ";
129 }
130
131 //
132 // The rest of the file are the traversal functions.  The last one
133 // is the one that starts the traversal.
134 //
135 // Return true from interior nodes to have the external traversal
136 // continue on to children.  If you process children yourself,
137 // return false.
138 //
139
140 bool TOutputTraverser::visitBinary(TVisit /* visit */, TIntermBinary* node)
141 {
142     TInfoSink& out = infoSink;
143
144     OutputTreeText(out, node, depth);
145
146     switch (node->getOp()) {
147     case EOpAssign:                   out.debug << "move second child to first child";           break;
148     case EOpAddAssign:                out.debug << "add second child into first child";          break;
149     case EOpSubAssign:                out.debug << "subtract second child into first child";     break;
150     case EOpMulAssign:                out.debug << "multiply second child into first child";     break;
151     case EOpVectorTimesMatrixAssign:  out.debug << "matrix mult second child into first child";  break;
152     case EOpVectorTimesScalarAssign:  out.debug << "vector scale second child into first child"; break;
153     case EOpMatrixTimesScalarAssign:  out.debug << "matrix scale second child into first child"; break;
154     case EOpMatrixTimesMatrixAssign:  out.debug << "matrix mult second child into first child";  break;
155     case EOpDivAssign:                out.debug << "divide second child into first child";       break;
156     case EOpModAssign:                out.debug << "mod second child into first child";          break;
157     case EOpAndAssign:                out.debug << "and second child into first child";          break;
158     case EOpInclusiveOrAssign:        out.debug << "or second child into first child";           break;
159     case EOpExclusiveOrAssign:        out.debug << "exclusive or second child into first child"; break;
160     case EOpLeftShiftAssign:          out.debug << "left shift second child into first child";   break;
161     case EOpRightShiftAssign:         out.debug << "right shift second child into first child";  break;
162
163     case EOpIndexDirect:   out.debug << "direct index";   break;
164     case EOpIndexIndirect: out.debug << "indirect index"; break;
165     case EOpIndexDirectStruct:
166         out.debug << (*node->getLeft()->getType().getStruct())[node->getRight()->getAsConstantUnion()->getConstArray()[0].getIConst()].type->getFieldName();
167         out.debug << ": direct index for structure";      break;
168     case EOpVectorSwizzle: out.debug << "vector swizzle"; break;
169     case EOpMatrixSwizzle: out.debug << "matrix swizzle"; break;
170
171     case EOpAdd:    out.debug << "add";                     break;
172     case EOpSub:    out.debug << "subtract";                break;
173     case EOpMul:    out.debug << "component-wise multiply"; break;
174     case EOpDiv:    out.debug << "divide";                  break;
175     case EOpMod:    out.debug << "mod";                     break;
176     case EOpRightShift:  out.debug << "right-shift";  break;
177     case EOpLeftShift:   out.debug << "left-shift";   break;
178     case EOpAnd:         out.debug << "bitwise and";  break;
179     case EOpInclusiveOr: out.debug << "inclusive-or"; break;
180     case EOpExclusiveOr: out.debug << "exclusive-or"; break;
181     case EOpEqual:            out.debug << "Compare Equal";                 break;
182     case EOpNotEqual:         out.debug << "Compare Not Equal";             break;
183     case EOpLessThan:         out.debug << "Compare Less Than";             break;
184     case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
185     case EOpLessThanEqual:    out.debug << "Compare Less Than or Equal";    break;
186     case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
187     case EOpVectorEqual:      out.debug << "Equal";                         break;
188     case EOpVectorNotEqual:   out.debug << "NotEqual";                      break;
189
190     case EOpVectorTimesScalar: out.debug << "vector-scale";          break;
191     case EOpVectorTimesMatrix: out.debug << "vector-times-matrix";   break;
192     case EOpMatrixTimesVector: out.debug << "matrix-times-vector";   break;
193     case EOpMatrixTimesScalar: out.debug << "matrix-scale";          break;
194     case EOpMatrixTimesMatrix: out.debug << "matrix-multiply";       break;
195
196     case EOpLogicalOr:  out.debug << "logical-or";   break;
197     case EOpLogicalXor: out.debug << "logical-xor"; break;
198     case EOpLogicalAnd: out.debug << "logical-and"; break;
199
200     default: out.debug << "<unknown op>";
201     }
202
203     out.debug << " (" << node->getCompleteString() << ")";
204
205     out.debug << "\n";
206
207     return true;
208 }
209
210 bool TOutputTraverser::visitUnary(TVisit /* visit */, TIntermUnary* node)
211 {
212     TInfoSink& out = infoSink;
213
214     OutputTreeText(out, node, depth);
215
216     switch (node->getOp()) {
217     case EOpNegative:       out.debug << "Negate value";         break;
218     case EOpVectorLogicalNot:
219     case EOpLogicalNot:     out.debug << "Negate conditional";   break;
220     case EOpBitwiseNot:     out.debug << "Bitwise not";          break;
221
222     case EOpPostIncrement:  out.debug << "Post-Increment";       break;
223     case EOpPostDecrement:  out.debug << "Post-Decrement";       break;
224     case EOpPreIncrement:   out.debug << "Pre-Increment";        break;
225     case EOpPreDecrement:   out.debug << "Pre-Decrement";        break;
226
227     case EOpConvIntToBool:     out.debug << "Convert int to bool";     break;
228     case EOpConvUintToBool:    out.debug << "Convert uint to bool";    break;
229     case EOpConvFloatToBool:   out.debug << "Convert float to bool";   break;
230     case EOpConvDoubleToBool:  out.debug << "Convert double to bool";  break;
231     case EOpConvInt64ToBool:   out.debug << "Convert int64 to bool";   break;
232     case EOpConvUint64ToBool:  out.debug << "Convert uint64 to bool";  break;
233     case EOpConvIntToFloat:    out.debug << "Convert int to float";    break;
234     case EOpConvUintToFloat:   out.debug << "Convert uint to float";   break;
235     case EOpConvDoubleToFloat: out.debug << "Convert double to float"; break;
236     case EOpConvInt64ToFloat:  out.debug << "Convert int64 to float";  break;
237     case EOpConvUint64ToFloat: out.debug << "Convert uint64 to float"; break;
238     case EOpConvBoolToFloat:   out.debug << "Convert bool to float";   break;
239     case EOpConvUintToInt:     out.debug << "Convert uint to int";     break;
240     case EOpConvFloatToInt:    out.debug << "Convert float to int";    break;
241     case EOpConvDoubleToInt:   out.debug << "Convert double to int";   break;
242     case EOpConvBoolToInt:     out.debug << "Convert bool to int";     break;
243     case EOpConvInt64ToInt:    out.debug << "Convert int64 to int";    break;
244     case EOpConvUint64ToInt:   out.debug << "Convert uint64 to int";   break;
245     case EOpConvIntToUint:     out.debug << "Convert int to uint";     break;
246     case EOpConvFloatToUint:   out.debug << "Convert float to uint";   break;
247     case EOpConvDoubleToUint:  out.debug << "Convert double to uint";  break;
248     case EOpConvBoolToUint:    out.debug << "Convert bool to uint";    break;
249     case EOpConvInt64ToUint:   out.debug << "Convert int64 to uint";   break;
250     case EOpConvUint64ToUint:  out.debug << "Convert uint64 to uint";  break;
251     case EOpConvIntToDouble:   out.debug << "Convert int to double";   break;
252     case EOpConvUintToDouble:  out.debug << "Convert uint to double";  break;
253     case EOpConvFloatToDouble: out.debug << "Convert float to double"; break;
254     case EOpConvBoolToDouble:  out.debug << "Convert bool to double";  break;
255     case EOpConvInt64ToDouble: out.debug << "Convert int64 to double"; break;
256     case EOpConvUint64ToDouble: out.debug << "Convert uint64 to double";  break;
257     case EOpConvBoolToInt64:   out.debug << "Convert bool to int64";   break;
258     case EOpConvIntToInt64:    out.debug << "Convert int to int64";    break;
259     case EOpConvUintToInt64:   out.debug << "Convert uint to int64";   break;
260     case EOpConvFloatToInt64:  out.debug << "Convert float to int64";  break;
261     case EOpConvDoubleToInt64: out.debug << "Convert double to int64"; break;
262     case EOpConvUint64ToInt64: out.debug << "Convert uint64 to int64"; break;
263     case EOpConvBoolToUint64:  out.debug << "Convert bool to uint64";  break;
264     case EOpConvIntToUint64:   out.debug << "Convert int to uint64";   break;
265     case EOpConvUintToUint64:  out.debug << "Convert uint to uint64";  break;
266     case EOpConvFloatToUint64: out.debug << "Convert float to uint64"; break;
267     case EOpConvDoubleToUint64: out.debug << "Convert double to uint64"; break;
268     case EOpConvInt64ToUint64: out.debug << "Convert uint64 to uint64"; break;
269
270     case EOpRadians:        out.debug << "radians";              break;
271     case EOpDegrees:        out.debug << "degrees";              break;
272     case EOpSin:            out.debug << "sine";                 break;
273     case EOpCos:            out.debug << "cosine";               break;
274     case EOpTan:            out.debug << "tangent";              break;
275     case EOpAsin:           out.debug << "arc sine";             break;
276     case EOpAcos:           out.debug << "arc cosine";           break;
277     case EOpAtan:           out.debug << "arc tangent";          break;
278     case EOpSinh:           out.debug << "hyp. sine";            break;
279     case EOpCosh:           out.debug << "hyp. cosine";          break;
280     case EOpTanh:           out.debug << "hyp. tangent";         break;
281     case EOpAsinh:          out.debug << "arc hyp. sine";        break;
282     case EOpAcosh:          out.debug << "arc hyp. cosine";      break;
283     case EOpAtanh:          out.debug << "arc hyp. tangent";     break;
284
285     case EOpExp:            out.debug << "exp";                  break;
286     case EOpLog:            out.debug << "log";                  break;
287     case EOpExp2:           out.debug << "exp2";                 break;
288     case EOpLog2:           out.debug << "log2";                 break;
289     case EOpSqrt:           out.debug << "sqrt";                 break;
290     case EOpInverseSqrt:    out.debug << "inverse sqrt";         break;
291
292     case EOpAbs:            out.debug << "Absolute value";       break;
293     case EOpSign:           out.debug << "Sign";                 break;
294     case EOpFloor:          out.debug << "Floor";                break;
295     case EOpTrunc:          out.debug << "trunc";                break;
296     case EOpRound:          out.debug << "round";                break;
297     case EOpRoundEven:      out.debug << "roundEven";            break;
298     case EOpCeil:           out.debug << "Ceiling";              break;
299     case EOpFract:          out.debug << "Fraction";             break;
300
301     case EOpIsNan:          out.debug << "isnan";                break;
302     case EOpIsInf:          out.debug << "isinf";                break;
303
304     case EOpFloatBitsToInt: out.debug << "floatBitsToInt";       break;
305     case EOpFloatBitsToUint:out.debug << "floatBitsToUint";      break;
306     case EOpIntBitsToFloat: out.debug << "intBitsToFloat";       break;
307     case EOpUintBitsToFloat:out.debug << "uintBitsToFloat";      break;
308     case EOpDoubleBitsToInt64:  out.debug << "doubleBitsToInt64";  break;
309     case EOpDoubleBitsToUint64: out.debug << "doubleBitsToUint64"; break;
310     case EOpInt64BitsToDouble:  out.debug << "int64BitsToDouble";  break;
311     case EOpUint64BitsToDouble: out.debug << "uint64BitsToDouble"; break;
312 #ifdef AMD_EXTENSIONS
313     case EOpFloat16BitsToInt16:  out.debug << "float16BitsToInt16";  break;
314     case EOpFloat16BitsToUint16: out.debug << "float16BitsToUint16"; break;
315     case EOpInt16BitsToFloat16:  out.debug << "int16BitsToFloat16";  break;
316     case EOpUint16BitsToFloat16: out.debug << "uint16BitsToFloat16"; break;
317 #endif
318
319     case EOpPackSnorm2x16:  out.debug << "packSnorm2x16";        break;
320     case EOpUnpackSnorm2x16:out.debug << "unpackSnorm2x16";      break;
321     case EOpPackUnorm2x16:  out.debug << "packUnorm2x16";        break;
322     case EOpUnpackUnorm2x16:out.debug << "unpackUnorm2x16";      break;
323     case EOpPackHalf2x16:   out.debug << "packHalf2x16";         break;
324     case EOpUnpackHalf2x16: out.debug << "unpackHalf2x16";       break;
325
326     case EOpPackSnorm4x8:     out.debug << "PackSnorm4x8";       break;
327     case EOpUnpackSnorm4x8:   out.debug << "UnpackSnorm4x8";     break;
328     case EOpPackUnorm4x8:     out.debug << "PackUnorm4x8";       break;
329     case EOpUnpackUnorm4x8:   out.debug << "UnpackUnorm4x8";     break;
330     case EOpPackDouble2x32:   out.debug << "PackDouble2x32";     break;
331     case EOpUnpackDouble2x32: out.debug << "UnpackDouble2x32";   break;
332
333     case EOpPackInt2x32:      out.debug << "packInt2x32";        break;
334     case EOpUnpackInt2x32:    out.debug << "unpackInt2x32";      break;
335     case EOpPackUint2x32:     out.debug << "packUint2x32";       break;
336     case EOpUnpackUint2x32:   out.debug << "unpackUint2x32";     break;
337
338 #ifdef AMD_EXTENSIONS
339     case EOpPackInt2x16:      out.debug << "packInt2x16";        break;
340     case EOpUnpackInt2x16:    out.debug << "unpackInt2x16";      break;
341     case EOpPackUint2x16:     out.debug << "packUint2x16";       break;
342     case EOpUnpackUint2x16:   out.debug << "unpackUint2x16";     break;
343
344     case EOpPackInt4x16:      out.debug << "packInt4x16";        break;
345     case EOpUnpackInt4x16:    out.debug << "unpackInt4x16";      break;
346     case EOpPackUint4x16:     out.debug << "packUint4x16";       break;
347     case EOpUnpackUint4x16:   out.debug << "unpackUint4x16";     break;
348
349     case EOpPackFloat2x16:    out.debug << "packFloat2x16";      break;
350     case EOpUnpackFloat2x16:  out.debug << "unpackFloat2x16";    break;
351 #endif
352
353     case EOpLength:         out.debug << "length";               break;
354     case EOpNormalize:      out.debug << "normalize";            break;
355     case EOpDPdx:           out.debug << "dPdx";                 break;
356     case EOpDPdy:           out.debug << "dPdy";                 break;
357     case EOpFwidth:         out.debug << "fwidth";               break;
358     case EOpDPdxFine:       out.debug << "dPdxFine";             break;
359     case EOpDPdyFine:       out.debug << "dPdyFine";             break;
360     case EOpFwidthFine:     out.debug << "fwidthFine";           break;
361     case EOpDPdxCoarse:     out.debug << "dPdxCoarse";           break;
362     case EOpDPdyCoarse:     out.debug << "dPdyCoarse";           break;
363     case EOpFwidthCoarse:   out.debug << "fwidthCoarse";         break;
364
365     case EOpInterpolateAtCentroid: out.debug << "interpolateAtCentroid";  break;
366
367     case EOpDeterminant:    out.debug << "determinant";          break;
368     case EOpMatrixInverse:  out.debug << "inverse";              break;
369     case EOpTranspose:      out.debug << "transpose";            break;
370
371     case EOpAny:            out.debug << "any";                  break;
372     case EOpAll:            out.debug << "all";                  break;
373
374     case EOpArrayLength:    out.debug << "array length";         break;
375
376     case EOpEmitStreamVertex:   out.debug << "EmitStreamVertex";   break;
377     case EOpEndStreamPrimitive: out.debug << "EndStreamPrimitive"; break;
378
379     case EOpAtomicCounterIncrement: out.debug << "AtomicCounterIncrement";break;
380     case EOpAtomicCounterDecrement: out.debug << "AtomicCounterDecrement";break;
381     case EOpAtomicCounter:          out.debug << "AtomicCounter";         break;
382
383     case EOpTextureQuerySize:       out.debug << "textureSize";           break;
384     case EOpTextureQueryLod:        out.debug << "textureQueryLod";       break;
385     case EOpTextureQueryLevels:     out.debug << "textureQueryLevels";    break;
386     case EOpTextureQuerySamples:    out.debug << "textureSamples";        break;
387     case EOpImageQuerySize:         out.debug << "imageQuerySize";        break;
388     case EOpImageQuerySamples:      out.debug << "imageQuerySamples";     break;
389     case EOpImageLoad:              out.debug << "imageLoad";             break;
390
391     case EOpBitFieldReverse:        out.debug << "bitFieldReverse";       break;
392     case EOpBitCount:               out.debug << "bitCount";              break;
393     case EOpFindLSB:                out.debug << "findLSB";               break;
394     case EOpFindMSB:                out.debug << "findMSB";               break;
395
396     case EOpNoise:                  out.debug << "noise";                 break;
397
398     case EOpBallot:                 out.debug << "ballot";                break;
399     case EOpReadFirstInvocation:    out.debug << "readFirstInvocation";   break;
400
401     case EOpAnyInvocation:          out.debug << "anyInvocation";         break;
402     case EOpAllInvocations:         out.debug << "allInvocations";        break;
403     case EOpAllInvocationsEqual:    out.debug << "allInvocationsEqual";   break;
404
405     case EOpClip:                   out.debug << "clip";                  break;
406     case EOpIsFinite:               out.debug << "isfinite";              break;
407     case EOpLog10:                  out.debug << "log10";                 break;
408     case EOpRcp:                    out.debug << "rcp";                   break;
409     case EOpSaturate:               out.debug << "saturate";              break;
410
411     case EOpSparseTexelsResident:   out.debug << "sparseTexelsResident";  break;
412
413 #ifdef AMD_EXTENSIONS
414     case EOpMinInvocations:             out.debug << "minInvocations";              break;
415     case EOpMaxInvocations:             out.debug << "maxInvocations";              break;
416     case EOpAddInvocations:             out.debug << "addInvocations";              break;
417     case EOpMinInvocationsNonUniform:   out.debug << "minInvocationsNonUniform";    break;
418     case EOpMaxInvocationsNonUniform:   out.debug << "maxInvocationsNonUniform";    break;
419     case EOpAddInvocationsNonUniform:   out.debug << "addInvocationsNonUniform";    break;
420
421     case EOpMinInvocationsInclusiveScan:            out.debug << "minInvocationsInclusiveScan";             break;
422     case EOpMaxInvocationsInclusiveScan:            out.debug << "maxInvocationsInclusiveScan";             break;
423     case EOpAddInvocationsInclusiveScan:            out.debug << "addInvocationsInclusiveScan";             break;
424     case EOpMinInvocationsInclusiveScanNonUniform:  out.debug << "minInvocationsInclusiveScanNonUniform";   break;
425     case EOpMaxInvocationsInclusiveScanNonUniform:  out.debug << "maxInvocationsInclusiveScanNonUniform";   break;
426     case EOpAddInvocationsInclusiveScanNonUniform:  out.debug << "addInvocationsInclusiveScanNonUniform";   break;
427
428     case EOpMinInvocationsExclusiveScan:            out.debug << "minInvocationsExclusiveScan";             break;
429     case EOpMaxInvocationsExclusiveScan:            out.debug << "maxInvocationsExclusiveScan";             break;
430     case EOpAddInvocationsExclusiveScan:            out.debug << "addInvocationsExclusiveScan";             break;
431     case EOpMinInvocationsExclusiveScanNonUniform:  out.debug << "minInvocationsExclusiveScanNonUniform";   break;
432     case EOpMaxInvocationsExclusiveScanNonUniform:  out.debug << "maxInvocationsExclusiveScanNonUniform";   break;
433     case EOpAddInvocationsExclusiveScanNonUniform:  out.debug << "addInvocationsExclusiveScanNonUniform";   break;
434
435     case EOpMbcnt:                  out.debug << "mbcnt";                       break;
436
437     case EOpCubeFaceIndex:          out.debug << "cubeFaceIndex";               break;
438     case EOpCubeFaceCoord:          out.debug << "cubeFaceCoord";               break;
439
440     case EOpFragmentMaskFetch:      out.debug << "fragmentMaskFetchAMD";        break;
441     case EOpFragmentFetch:          out.debug << "fragmentFetchAMD";            break;
442
443     case EOpConvBoolToFloat16:      out.debug << "Convert bool to float16";     break;
444     case EOpConvIntToFloat16:       out.debug << "Convert int to float16";      break;
445     case EOpConvUintToFloat16:      out.debug << "Convert uint to float16";     break;
446     case EOpConvFloatToFloat16:     out.debug << "Convert float to float16";    break;
447     case EOpConvDoubleToFloat16:    out.debug << "Convert double to float16";   break;
448     case EOpConvInt64ToFloat16:     out.debug << "Convert int64 to float16";    break;
449     case EOpConvUint64ToFloat16:    out.debug << "Convert uint64 to float16";   break;
450     case EOpConvFloat16ToBool:      out.debug << "Convert float16 to bool";     break;
451     case EOpConvFloat16ToInt:       out.debug << "Convert float16 to int";      break;
452     case EOpConvFloat16ToUint:      out.debug << "Convert float16 to uint";     break;
453     case EOpConvFloat16ToFloat:     out.debug << "Convert float16 to float";    break;
454     case EOpConvFloat16ToDouble:    out.debug << "Convert float16 to double";   break;
455     case EOpConvFloat16ToInt64:     out.debug << "Convert float16 to int64";    break;
456     case EOpConvFloat16ToUint64:    out.debug << "Convert float16 to uint64";   break;
457
458     case EOpConvBoolToInt16:        out.debug << "Convert bool to int16";       break;
459     case EOpConvIntToInt16:         out.debug << "Convert int to int16";        break;
460     case EOpConvUintToInt16:        out.debug << "Convert uint to int16";       break;
461     case EOpConvFloatToInt16:       out.debug << "Convert float to int16";      break;
462     case EOpConvDoubleToInt16:      out.debug << "Convert double to int16";     break;
463     case EOpConvFloat16ToInt16:     out.debug << "Convert float16 to int16";    break;
464     case EOpConvInt64ToInt16:       out.debug << "Convert int64 to int16";      break;
465     case EOpConvUint64ToInt16:      out.debug << "Convert uint64 to int16";     break;
466     case EOpConvUint16ToInt16:      out.debug << "Convert uint16 to int16";     break;
467     case EOpConvInt16ToBool:        out.debug << "Convert int16 to bool";       break;
468     case EOpConvInt16ToInt:         out.debug << "Convert int16 to int";        break;
469     case EOpConvInt16ToUint:        out.debug << "Convert int16 to uint";       break;
470     case EOpConvInt16ToFloat:       out.debug << "Convert int16 to float";      break;
471     case EOpConvInt16ToDouble:      out.debug << "Convert int16 to double";     break;
472     case EOpConvInt16ToFloat16:     out.debug << "Convert int16 to float16";    break;
473     case EOpConvInt16ToInt64:       out.debug << "Convert int16 to int64";      break;
474     case EOpConvInt16ToUint64:      out.debug << "Convert int16 to uint64";     break;
475
476     case EOpConvBoolToUint16:       out.debug << "Convert bool to uint16";      break;
477     case EOpConvIntToUint16:        out.debug << "Convert int to uint16";       break;
478     case EOpConvUintToUint16:       out.debug << "Convert uint to uint16";      break;
479     case EOpConvFloatToUint16:      out.debug << "Convert float to uint16";     break;
480     case EOpConvDoubleToUint16:     out.debug << "Convert double to uint16";    break;
481     case EOpConvFloat16ToUint16:    out.debug << "Convert float16 to uint16";   break;
482     case EOpConvInt64ToUint16:      out.debug << "Convert int64 to uint16";     break;
483     case EOpConvUint64ToUint16:     out.debug << "Convert uint64 to uint16";    break;
484     case EOpConvInt16ToUint16:      out.debug << "Convert int16 to uint16";     break;
485     case EOpConvUint16ToBool:       out.debug << "Convert uint16 to bool";      break;
486     case EOpConvUint16ToInt:        out.debug << "Convert uint16 to int";       break;
487     case EOpConvUint16ToUint:       out.debug << "Convert uint16 to uint";      break;
488     case EOpConvUint16ToFloat:      out.debug << "Convert uint16 to float";     break;
489     case EOpConvUint16ToDouble:     out.debug << "Convert uint16 to double";    break;
490     case EOpConvUint16ToFloat16:    out.debug << "Convert uint16 to float16";   break;
491     case EOpConvUint16ToInt64:      out.debug << "Convert uint16 to int64";     break;
492     case EOpConvUint16ToUint64:     out.debug << "Convert uint16 to uint64";    break;
493 #endif
494
495     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
496     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
497
498     default: out.debug.message(EPrefixError, "Bad unary op");
499     }
500
501     out.debug << " (" << node->getCompleteString() << ")";
502
503     out.debug << "\n";
504
505     return true;
506 }
507
508 bool TOutputTraverser::visitAggregate(TVisit /* visit */, TIntermAggregate* node)
509 {
510     TInfoSink& out = infoSink;
511
512     if (node->getOp() == EOpNull) {
513         out.debug.message(EPrefixError, "node is still EOpNull!");
514         return true;
515     }
516
517     OutputTreeText(out, node, depth);
518
519     switch (node->getOp()) {
520     case EOpSequence:      out.debug << "Sequence\n";       return true;
521     case EOpLinkerObjects: out.debug << "Linker Objects\n"; return true;
522     case EOpComma:         out.debug << "Comma";            break;
523     case EOpFunction:      out.debug << "Function Definition: " << node->getName(); break;
524     case EOpFunctionCall:  out.debug << "Function Call: "       << node->getName(); break;
525     case EOpParameters:    out.debug << "Function Parameters: ";                    break;
526
527     case EOpConstructFloat: out.debug << "Construct float"; break;
528     case EOpConstructDouble:out.debug << "Construct double"; break;
529
530     case EOpConstructVec2:  out.debug << "Construct vec2";  break;
531     case EOpConstructVec3:  out.debug << "Construct vec3";  break;
532     case EOpConstructVec4:  out.debug << "Construct vec4";  break;
533     case EOpConstructDVec2: out.debug << "Construct dvec2";  break;
534     case EOpConstructDVec3: out.debug << "Construct dvec3";  break;
535     case EOpConstructDVec4: out.debug << "Construct dvec4";  break;
536     case EOpConstructBool:  out.debug << "Construct bool";  break;
537     case EOpConstructBVec2: out.debug << "Construct bvec2"; break;
538     case EOpConstructBVec3: out.debug << "Construct bvec3"; break;
539     case EOpConstructBVec4: out.debug << "Construct bvec4"; break;
540     case EOpConstructInt:   out.debug << "Construct int";   break;
541     case EOpConstructIVec2: out.debug << "Construct ivec2"; break;
542     case EOpConstructIVec3: out.debug << "Construct ivec3"; break;
543     case EOpConstructIVec4: out.debug << "Construct ivec4"; break;
544     case EOpConstructUint:    out.debug << "Construct uint";    break;
545     case EOpConstructUVec2:   out.debug << "Construct uvec2";   break;
546     case EOpConstructUVec3:   out.debug << "Construct uvec3";   break;
547     case EOpConstructUVec4:   out.debug << "Construct uvec4";   break;
548     case EOpConstructInt64:   out.debug << "Construct int64_t"; break;
549     case EOpConstructI64Vec2: out.debug << "Construct i64vec2"; break;
550     case EOpConstructI64Vec3: out.debug << "Construct i64vec3"; break;
551     case EOpConstructI64Vec4: out.debug << "Construct i64vec4"; break;
552     case EOpConstructUint64:  out.debug << "Construct uint64_t"; break;
553     case EOpConstructU64Vec2: out.debug << "Construct u64vec2"; break;
554     case EOpConstructU64Vec3: out.debug << "Construct u64vec3"; break;
555     case EOpConstructU64Vec4: out.debug << "Construct u64vec4"; break;
556 #ifdef AMD_EXTENSIONS
557     case EOpConstructInt16:   out.debug << "Construct int16_t"; break;
558     case EOpConstructI16Vec2: out.debug << "Construct i16vec2"; break;
559     case EOpConstructI16Vec3: out.debug << "Construct i16vec3"; break;
560     case EOpConstructI16Vec4: out.debug << "Construct i16vec4"; break;
561     case EOpConstructUint16:  out.debug << "Construct uint16_t"; break;
562     case EOpConstructU16Vec2: out.debug << "Construct u16vec2"; break;
563     case EOpConstructU16Vec3: out.debug << "Construct u16vec3"; break;
564     case EOpConstructU16Vec4: out.debug << "Construct u16vec4"; break;
565 #endif
566     case EOpConstructMat2x2:  out.debug << "Construct mat2";    break;
567     case EOpConstructMat2x3:  out.debug << "Construct mat2x3";  break;
568     case EOpConstructMat2x4:  out.debug << "Construct mat2x4";  break;
569     case EOpConstructMat3x2:  out.debug << "Construct mat3x2";  break;
570     case EOpConstructMat3x3:  out.debug << "Construct mat3";    break;
571     case EOpConstructMat3x4:  out.debug << "Construct mat3x4";  break;
572     case EOpConstructMat4x2:  out.debug << "Construct mat4x2";  break;
573     case EOpConstructMat4x3:  out.debug << "Construct mat4x3";  break;
574     case EOpConstructMat4x4:  out.debug << "Construct mat4";    break;
575     case EOpConstructDMat2x2: out.debug << "Construct dmat2";   break;
576     case EOpConstructDMat2x3: out.debug << "Construct dmat2x3"; break;
577     case EOpConstructDMat2x4: out.debug << "Construct dmat2x4"; break;
578     case EOpConstructDMat3x2: out.debug << "Construct dmat3x2"; break;
579     case EOpConstructDMat3x3: out.debug << "Construct dmat3";   break;
580     case EOpConstructDMat3x4: out.debug << "Construct dmat3x4"; break;
581     case EOpConstructDMat4x2: out.debug << "Construct dmat4x2"; break;
582     case EOpConstructDMat4x3: out.debug << "Construct dmat4x3"; break;
583     case EOpConstructDMat4x4: out.debug << "Construct dmat4";   break;
584     case EOpConstructIMat2x2: out.debug << "Construct imat2";   break;
585     case EOpConstructIMat2x3: out.debug << "Construct imat2x3"; break;
586     case EOpConstructIMat2x4: out.debug << "Construct imat2x4"; break;
587     case EOpConstructIMat3x2: out.debug << "Construct imat3x2"; break;
588     case EOpConstructIMat3x3: out.debug << "Construct imat3";   break;
589     case EOpConstructIMat3x4: out.debug << "Construct imat3x4"; break;
590     case EOpConstructIMat4x2: out.debug << "Construct imat4x2"; break;
591     case EOpConstructIMat4x3: out.debug << "Construct imat4x3"; break;
592     case EOpConstructIMat4x4: out.debug << "Construct imat4";   break;
593     case EOpConstructUMat2x2: out.debug << "Construct umat2";   break;
594     case EOpConstructUMat2x3: out.debug << "Construct umat2x3"; break;
595     case EOpConstructUMat2x4: out.debug << "Construct umat2x4"; break;
596     case EOpConstructUMat3x2: out.debug << "Construct umat3x2"; break;
597     case EOpConstructUMat3x3: out.debug << "Construct umat3";   break;
598     case EOpConstructUMat3x4: out.debug << "Construct umat3x4"; break;
599     case EOpConstructUMat4x2: out.debug << "Construct umat4x2"; break;
600     case EOpConstructUMat4x3: out.debug << "Construct umat4x3"; break;
601     case EOpConstructUMat4x4: out.debug << "Construct umat4";   break;
602     case EOpConstructBMat2x2: out.debug << "Construct bmat2";   break;
603     case EOpConstructBMat2x3: out.debug << "Construct bmat2x3"; break;
604     case EOpConstructBMat2x4: out.debug << "Construct bmat2x4"; break;
605     case EOpConstructBMat3x2: out.debug << "Construct bmat3x2"; break;
606     case EOpConstructBMat3x3: out.debug << "Construct bmat3";   break;
607     case EOpConstructBMat3x4: out.debug << "Construct bmat3x4"; break;
608     case EOpConstructBMat4x2: out.debug << "Construct bmat4x2"; break;
609     case EOpConstructBMat4x3: out.debug << "Construct bmat4x3"; break;
610     case EOpConstructBMat4x4: out.debug << "Construct bmat4";   break;
611 #ifdef AMD_EXTENSIONS
612     case EOpConstructFloat16:   out.debug << "Construct float16_t"; break;
613     case EOpConstructF16Vec2:   out.debug << "Construct f16vec2";   break;
614     case EOpConstructF16Vec3:   out.debug << "Construct f16vec3";   break;
615     case EOpConstructF16Vec4:   out.debug << "Construct f16vec4";   break;
616     case EOpConstructF16Mat2x2: out.debug << "Construct f16mat2";   break;
617     case EOpConstructF16Mat2x3: out.debug << "Construct f16mat2x3"; break;
618     case EOpConstructF16Mat2x4: out.debug << "Construct f16mat2x4"; break;
619     case EOpConstructF16Mat3x2: out.debug << "Construct f16mat3x2"; break;
620     case EOpConstructF16Mat3x3: out.debug << "Construct f16mat3";   break;
621     case EOpConstructF16Mat3x4: out.debug << "Construct f16mat3x4"; break;
622     case EOpConstructF16Mat4x2: out.debug << "Construct f16mat4x2"; break;
623     case EOpConstructF16Mat4x3: out.debug << "Construct f16mat4x3"; break;
624     case EOpConstructF16Mat4x4: out.debug << "Construct f16mat4";   break;
625 #endif
626     case EOpConstructStruct:  out.debug << "Construct structure";  break;
627     case EOpConstructTextureSampler: out.debug << "Construct combined texture-sampler"; break;
628
629     case EOpLessThan:         out.debug << "Compare Less Than";             break;
630     case EOpGreaterThan:      out.debug << "Compare Greater Than";          break;
631     case EOpLessThanEqual:    out.debug << "Compare Less Than or Equal";    break;
632     case EOpGreaterThanEqual: out.debug << "Compare Greater Than or Equal"; break;
633     case EOpVectorEqual:      out.debug << "Equal";                         break;
634     case EOpVectorNotEqual:   out.debug << "NotEqual";                      break;
635
636     case EOpMod:           out.debug << "mod";         break;
637     case EOpModf:          out.debug << "modf";        break;
638     case EOpPow:           out.debug << "pow";         break;
639
640     case EOpAtan:          out.debug << "arc tangent"; break;
641
642     case EOpMin:           out.debug << "min";         break;
643     case EOpMax:           out.debug << "max";         break;
644     case EOpClamp:         out.debug << "clamp";       break;
645     case EOpMix:           out.debug << "mix";         break;
646     case EOpStep:          out.debug << "step";        break;
647     case EOpSmoothStep:    out.debug << "smoothstep";  break;
648
649     case EOpDistance:      out.debug << "distance";                break;
650     case EOpDot:           out.debug << "dot-product";             break;
651     case EOpCross:         out.debug << "cross-product";           break;
652     case EOpFaceForward:   out.debug << "face-forward";            break;
653     case EOpReflect:       out.debug << "reflect";                 break;
654     case EOpRefract:       out.debug << "refract";                 break;
655     case EOpMul:           out.debug << "component-wise multiply"; break;
656     case EOpOuterProduct:  out.debug << "outer product";           break;
657
658     case EOpEmitVertex:    out.debug << "EmitVertex";              break;
659     case EOpEndPrimitive:  out.debug << "EndPrimitive";            break;
660
661     case EOpBarrier:                    out.debug << "Barrier";                    break;
662     case EOpMemoryBarrier:              out.debug << "MemoryBarrier";              break;
663     case EOpMemoryBarrierAtomicCounter: out.debug << "MemoryBarrierAtomicCounter"; break;
664     case EOpMemoryBarrierBuffer:        out.debug << "MemoryBarrierBuffer";        break;
665     case EOpMemoryBarrierImage:         out.debug << "MemoryBarrierImage";         break;
666     case EOpMemoryBarrierShared:        out.debug << "MemoryBarrierShared";        break;
667     case EOpGroupMemoryBarrier:         out.debug << "GroupMemoryBarrier";         break;
668
669     case EOpReadInvocation:             out.debug << "readInvocation";        break;
670
671 #ifdef AMD_EXTENSIONS
672     case EOpSwizzleInvocations:         out.debug << "swizzleInvocations";       break;
673     case EOpSwizzleInvocationsMasked:   out.debug << "swizzleInvocationsMasked"; break;
674     case EOpWriteInvocation:            out.debug << "writeInvocation";          break;
675
676     case EOpMin3:                       out.debug << "min3";                  break;
677     case EOpMax3:                       out.debug << "max3";                  break;
678     case EOpMid3:                       out.debug << "mid3";                  break;
679
680     case EOpTime:                       out.debug << "time";                  break;
681 #endif
682
683     case EOpAtomicAdd:                  out.debug << "AtomicAdd";             break;
684     case EOpAtomicMin:                  out.debug << "AtomicMin";             break;
685     case EOpAtomicMax:                  out.debug << "AtomicMax";             break;
686     case EOpAtomicAnd:                  out.debug << "AtomicAnd";             break;
687     case EOpAtomicOr:                   out.debug << "AtomicOr";              break;
688     case EOpAtomicXor:                  out.debug << "AtomicXor";             break;
689     case EOpAtomicExchange:             out.debug << "AtomicExchange";        break;
690     case EOpAtomicCompSwap:             out.debug << "AtomicCompSwap";        break;
691
692     case EOpAtomicCounterAdd:           out.debug << "AtomicCounterAdd";      break;
693     case EOpAtomicCounterSubtract:      out.debug << "AtomicCounterSubtract"; break;
694     case EOpAtomicCounterMin:           out.debug << "AtomicCounterMin";      break;
695     case EOpAtomicCounterMax:           out.debug << "AtomicCounterMax";      break;
696     case EOpAtomicCounterAnd:           out.debug << "AtomicCounterAnd";      break;
697     case EOpAtomicCounterOr:            out.debug << "AtomicCounterOr";       break;
698     case EOpAtomicCounterXor:           out.debug << "AtomicCounterXor";      break;
699     case EOpAtomicCounterExchange:      out.debug << "AtomicCounterExchange"; break;
700     case EOpAtomicCounterCompSwap:      out.debug << "AtomicCounterCompSwap"; break;
701
702     case EOpImageQuerySize:             out.debug << "imageQuerySize";        break;
703     case EOpImageQuerySamples:          out.debug << "imageQuerySamples";     break;
704     case EOpImageLoad:                  out.debug << "imageLoad";             break;
705     case EOpImageStore:                 out.debug << "imageStore";            break;
706     case EOpImageAtomicAdd:             out.debug << "imageAtomicAdd";        break;
707     case EOpImageAtomicMin:             out.debug << "imageAtomicMin";        break;
708     case EOpImageAtomicMax:             out.debug << "imageAtomicMax";        break;
709     case EOpImageAtomicAnd:             out.debug << "imageAtomicAnd";        break;
710     case EOpImageAtomicOr:              out.debug << "imageAtomicOr";         break;
711     case EOpImageAtomicXor:             out.debug << "imageAtomicXor";        break;
712     case EOpImageAtomicExchange:        out.debug << "imageAtomicExchange";   break;
713     case EOpImageAtomicCompSwap:        out.debug << "imageAtomicCompSwap";   break;
714 #ifdef AMD_EXTENSIONS
715     case EOpImageLoadLod:               out.debug << "imageLoadLod";          break;
716     case EOpImageStoreLod:              out.debug << "imageStoreLod";         break;
717 #endif
718
719     case EOpTextureQuerySize:           out.debug << "textureSize";           break;
720     case EOpTextureQueryLod:            out.debug << "textureQueryLod";       break;
721     case EOpTextureQueryLevels:         out.debug << "textureQueryLevels";    break;
722     case EOpTextureQuerySamples:        out.debug << "textureSamples";        break;
723     case EOpTexture:                    out.debug << "texture";               break;
724     case EOpTextureProj:                out.debug << "textureProj";           break;
725     case EOpTextureLod:                 out.debug << "textureLod";            break;
726     case EOpTextureOffset:              out.debug << "textureOffset";         break;
727     case EOpTextureFetch:               out.debug << "textureFetch";          break;
728     case EOpTextureFetchOffset:         out.debug << "textureFetchOffset";    break;
729     case EOpTextureProjOffset:          out.debug << "textureProjOffset";     break;
730     case EOpTextureLodOffset:           out.debug << "textureLodOffset";      break;
731     case EOpTextureProjLod:             out.debug << "textureProjLod";        break;
732     case EOpTextureProjLodOffset:       out.debug << "textureProjLodOffset";  break;
733     case EOpTextureGrad:                out.debug << "textureGrad";           break;
734     case EOpTextureGradOffset:          out.debug << "textureGradOffset";     break;
735     case EOpTextureProjGrad:            out.debug << "textureProjGrad";       break;
736     case EOpTextureProjGradOffset:      out.debug << "textureProjGradOffset"; break;
737     case EOpTextureGather:              out.debug << "textureGather";         break;
738     case EOpTextureGatherOffset:        out.debug << "textureGatherOffset";   break;
739     case EOpTextureGatherOffsets:       out.debug << "textureGatherOffsets";  break;
740     case EOpTextureClamp:               out.debug << "textureClamp";          break;
741     case EOpTextureOffsetClamp:         out.debug << "textureOffsetClamp";    break;
742     case EOpTextureGradClamp:           out.debug << "textureGradClamp";      break;
743     case EOpTextureGradOffsetClamp:     out.debug << "textureGradOffsetClamp";  break;
744 #ifdef AMD_EXTENSIONS
745     case EOpTextureGatherLod:           out.debug << "textureGatherLod";        break;
746     case EOpTextureGatherLodOffset:     out.debug << "textureGatherLodOffset";  break;
747     case EOpTextureGatherLodOffsets:    out.debug << "textureGatherLodOffsets"; break;
748 #endif
749
750     case EOpSparseTexture:                  out.debug << "sparseTexture";                   break;
751     case EOpSparseTextureOffset:            out.debug << "sparseTextureOffset";             break;
752     case EOpSparseTextureLod:               out.debug << "sparseTextureLod";                break;
753     case EOpSparseTextureLodOffset:         out.debug << "sparseTextureLodOffset";          break;
754     case EOpSparseTextureFetch:             out.debug << "sparseTexelFetch";                break;
755     case EOpSparseTextureFetchOffset:       out.debug << "sparseTexelFetchOffset";          break;
756     case EOpSparseTextureGrad:              out.debug << "sparseTextureGrad";               break;
757     case EOpSparseTextureGradOffset:        out.debug << "sparseTextureGradOffset";         break;
758     case EOpSparseTextureGather:            out.debug << "sparseTextureGather";             break;
759     case EOpSparseTextureGatherOffset:      out.debug << "sparseTextureGatherOffset";       break;
760     case EOpSparseTextureGatherOffsets:     out.debug << "sparseTextureGatherOffsets";      break;
761     case EOpSparseImageLoad:                out.debug << "sparseImageLoad";                 break;
762     case EOpSparseTextureClamp:             out.debug << "sparseTextureClamp";              break;
763     case EOpSparseTextureOffsetClamp:       out.debug << "sparseTextureOffsetClamp";        break;
764     case EOpSparseTextureGradClamp:         out.debug << "sparseTextureGradClamp";          break;
765     case EOpSparseTextureGradOffsetClamp:   out.debug << "sparseTextureGradOffsetClam";     break;
766 #ifdef AMD_EXTENSIONS
767     case EOpSparseTextureGatherLod:         out.debug << "sparseTextureGatherLod";          break;
768     case EOpSparseTextureGatherLodOffset:   out.debug << "sparseTextureGatherLodOffset";    break;
769     case EOpSparseTextureGatherLodOffsets:  out.debug << "sparseTextureGatherLodOffsets";   break;
770     case EOpSparseImageLoadLod:             out.debug << "sparseImageLoadLod";              break;
771 #endif
772
773     case EOpAddCarry:                   out.debug << "addCarry";              break;
774     case EOpSubBorrow:                  out.debug << "subBorrow";             break;
775     case EOpUMulExtended:               out.debug << "uMulExtended";          break;
776     case EOpIMulExtended:               out.debug << "iMulExtended";          break;
777     case EOpBitfieldExtract:            out.debug << "bitfieldExtract";       break;
778     case EOpBitfieldInsert:             out.debug << "bitfieldInsert";        break;
779
780     case EOpFma:                        out.debug << "fma";                   break;
781     case EOpFrexp:                      out.debug << "frexp";                 break;
782     case EOpLdexp:                      out.debug << "ldexp";                 break;
783
784     case EOpInterpolateAtSample:   out.debug << "interpolateAtSample";    break;
785     case EOpInterpolateAtOffset:   out.debug << "interpolateAtOffset";    break;
786 #ifdef AMD_EXTENSIONS
787     case EOpInterpolateAtVertex:   out.debug << "interpolateAtVertex";    break;
788 #endif
789
790     case EOpSinCos:                     out.debug << "sincos";                break;
791     case EOpGenMul:                     out.debug << "mul";                   break;
792
793     case EOpAllMemoryBarrierWithGroupSync:    out.debug << "AllMemoryBarrierWithGroupSync";    break;
794     case EOpDeviceMemoryBarrier:              out.debug << "DeviceMemoryBarrier";              break;
795     case EOpDeviceMemoryBarrierWithGroupSync: out.debug << "DeviceMemoryBarrierWithGroupSync"; break;
796     case EOpWorkgroupMemoryBarrier:           out.debug << "WorkgroupMemoryBarrier";           break;
797     case EOpWorkgroupMemoryBarrierWithGroupSync: out.debug << "WorkgroupMemoryBarrierWithGroupSync"; break;
798
799     case EOpSubpassLoad:   out.debug << "subpassLoad";   break;
800     case EOpSubpassLoadMS: out.debug << "subpassLoadMS"; break;
801
802     default: out.debug.message(EPrefixError, "Bad aggregation op");
803     }
804
805     if (node->getOp() != EOpSequence && node->getOp() != EOpParameters)
806         out.debug << " (" << node->getCompleteString() << ")";
807
808     out.debug << "\n";
809
810     return true;
811 }
812
813 bool TOutputTraverser::visitSelection(TVisit /* visit */, TIntermSelection* node)
814 {
815     TInfoSink& out = infoSink;
816
817     OutputTreeText(out, node, depth);
818
819     out.debug << "Test condition and select";
820     out.debug << " (" << node->getCompleteString() << ")";
821
822     if (node->getFlatten())
823         out.debug << ": Flatten";
824     if (node->getDontFlatten())
825         out.debug << ": DontFlatten";
826     out.debug << "\n";
827
828     ++depth;
829
830     OutputTreeText(out, node, depth);
831     out.debug << "Condition\n";
832     node->getCondition()->traverse(this);
833
834     OutputTreeText(out, node, depth);
835     if (node->getTrueBlock()) {
836         out.debug << "true case\n";
837         node->getTrueBlock()->traverse(this);
838     } else
839         out.debug << "true case is null\n";
840
841     if (node->getFalseBlock()) {
842         OutputTreeText(out, node, depth);
843         out.debug << "false case\n";
844         node->getFalseBlock()->traverse(this);
845     }
846
847     --depth;
848
849     return false;
850 }
851
852 static void OutputConstantUnion(TInfoSink& out, const TIntermTyped* node, const TConstUnionArray& constUnion, int depth)
853 {
854     int size = node->getType().computeNumComponents();
855
856     for (int i = 0; i < size; i++) {
857         OutputTreeText(out, node, depth);
858         switch (constUnion[i].getType()) {
859         case EbtBool:
860             if (constUnion[i].getBConst())
861                 out.debug << "true";
862             else
863                 out.debug << "false";
864
865             out.debug << " (" << "const bool" << ")";
866
867             out.debug << "\n";
868             break;
869         case EbtFloat:
870         case EbtDouble:
871 #ifdef AMD_EXTENSIONS
872         case EbtFloat16:
873 #endif
874             {
875                 const double value = constUnion[i].getDConst();
876                 // Print infinities and NaNs in a portable way.
877                 if (IsInfinity(value)) {
878                     if (value < 0)
879                         out.debug << "-1.#INF\n";
880                     else
881                         out.debug << "+1.#INF\n";
882                 } else if (IsNan(value))
883                     out.debug << "1.#IND\n";
884                 else {
885                     const int maxSize = 300;
886                     char buf[maxSize];
887                     snprintf(buf, maxSize, "%f", value);
888
889                     out.debug << buf << "\n";
890                 }
891             }
892             break;
893         case EbtInt:
894             {
895                 const int maxSize = 300;
896                 char buf[maxSize];
897                 snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int");
898
899                 out.debug << buf << "\n";
900             }
901             break;
902         case EbtUint:
903             {
904                 const int maxSize = 300;
905                 char buf[maxSize];
906                 snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint");
907
908                 out.debug << buf << "\n";
909             }
910             break;
911         case EbtInt64:
912             {
913                 const int maxSize = 300;
914                 char buf[maxSize];
915                 snprintf(buf, maxSize, "%lld (%s)", constUnion[i].getI64Const(), "const int64_t");
916
917                 out.debug << buf << "\n";
918             }
919             break;
920         case EbtUint64:
921             {
922                 const int maxSize = 300;
923                 char buf[maxSize];
924                 snprintf(buf, maxSize, "%llu (%s)", constUnion[i].getU64Const(), "const uint64_t");
925
926                 out.debug << buf << "\n";
927             }
928             break;
929 #ifdef AMD_EXTENSIONS
930         case EbtInt16:
931             {
932                 const int maxSize = 300;
933                 char buf[maxSize];
934                 snprintf(buf, maxSize, "%d (%s)", constUnion[i].getIConst(), "const int16_t");
935
936                 out.debug << buf << "\n";
937             }
938             break;
939         case EbtUint16:
940             {
941                 const int maxSize = 300;
942                 char buf[maxSize];
943                 snprintf(buf, maxSize, "%u (%s)", constUnion[i].getUConst(), "const uint16_t");
944
945                 out.debug << buf << "\n";
946             }
947             break;
948 #endif
949         default:
950             out.info.message(EPrefixInternalError, "Unknown constant", node->getLoc());
951             break;
952         }
953     }
954 }
955
956 void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
957 {
958     OutputTreeText(infoSink, node, depth);
959     infoSink.debug << "Constant:\n";
960
961     OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
962 }
963
964 void TOutputTraverser::visitSymbol(TIntermSymbol* node)
965 {
966     OutputTreeText(infoSink, node, depth);
967
968     infoSink.debug << "'" << node->getName() << "' (" << node->getCompleteString() << ")\n";
969
970     if (! node->getConstArray().empty())
971         OutputConstantUnion(infoSink, node, node->getConstArray(), depth + 1);
972     else if (node->getConstSubtree()) {
973         incrementDepth(node);
974         node->getConstSubtree()->traverse(this);
975         decrementDepth();
976     }
977 }
978
979 bool TOutputTraverser::visitLoop(TVisit /* visit */, TIntermLoop* node)
980 {
981     TInfoSink& out = infoSink;
982
983     OutputTreeText(out, node, depth);
984
985     out.debug << "Loop with condition ";
986     if (! node->testFirst())
987         out.debug << "not ";
988     out.debug << "tested first";
989
990     if (node->getUnroll())
991         out.debug << ": Unroll";
992     if (node->getDontUnroll())
993         out.debug << ": DontUnroll";
994     if (node->getLoopDependency()) {
995         out.debug << ": Dependency ";
996         out.debug << node->getLoopDependency();
997     }
998     out.debug << "\n";
999
1000     ++depth;
1001
1002     OutputTreeText(infoSink, node, depth);
1003     if (node->getTest()) {
1004         out.debug << "Loop Condition\n";
1005         node->getTest()->traverse(this);
1006     } else
1007         out.debug << "No loop condition\n";
1008
1009     OutputTreeText(infoSink, node, depth);
1010     if (node->getBody()) {
1011         out.debug << "Loop Body\n";
1012         node->getBody()->traverse(this);
1013     } else
1014         out.debug << "No loop body\n";
1015
1016     if (node->getTerminal()) {
1017         OutputTreeText(infoSink, node, depth);
1018         out.debug << "Loop Terminal Expression\n";
1019         node->getTerminal()->traverse(this);
1020     }
1021
1022     --depth;
1023
1024     return false;
1025 }
1026
1027 bool TOutputTraverser::visitBranch(TVisit /* visit*/, TIntermBranch* node)
1028 {
1029     TInfoSink& out = infoSink;
1030
1031     OutputTreeText(out, node, depth);
1032
1033     switch (node->getFlowOp()) {
1034     case EOpKill:      out.debug << "Branch: Kill";           break;
1035     case EOpBreak:     out.debug << "Branch: Break";          break;
1036     case EOpContinue:  out.debug << "Branch: Continue";       break;
1037     case EOpReturn:    out.debug << "Branch: Return";         break;
1038     case EOpCase:      out.debug << "case: ";                 break;
1039     case EOpDefault:   out.debug << "default: ";              break;
1040     default:               out.debug << "Branch: Unknown Branch"; break;
1041     }
1042
1043     if (node->getExpression()) {
1044         out.debug << " with expression\n";
1045         ++depth;
1046         node->getExpression()->traverse(this);
1047         --depth;
1048     } else
1049         out.debug << "\n";
1050
1051     return false;
1052 }
1053
1054 bool TOutputTraverser::visitSwitch(TVisit /* visit */, TIntermSwitch* node)
1055 {
1056     TInfoSink& out = infoSink;
1057
1058     OutputTreeText(out, node, depth);
1059     out.debug << "switch";
1060
1061     if (node->getFlatten())
1062         out.debug << ": Flatten";
1063     if (node->getDontFlatten())
1064         out.debug << ": DontFlatten";
1065     out.debug << "\n";
1066
1067     OutputTreeText(out, node, depth);
1068     out.debug << "condition\n";
1069     ++depth;
1070     node->getCondition()->traverse(this);
1071
1072     --depth;
1073     OutputTreeText(out, node, depth);
1074     out.debug << "body\n";
1075     ++depth;
1076     node->getBody()->traverse(this);
1077
1078     --depth;
1079
1080     return false;
1081 }
1082
1083 //
1084 // This function is the one to call externally to start the traversal.
1085 // Individual functions can be initialized to 0 to skip processing of that
1086 // type of node.  It's children will still be processed.
1087 //
1088 void TIntermediate::output(TInfoSink& infoSink, bool tree)
1089 {
1090     infoSink.debug << "Shader version: " << version << "\n";
1091     if (requestedExtensions.size() > 0) {
1092         for (auto extIt = requestedExtensions.begin(); extIt != requestedExtensions.end(); ++extIt)
1093             infoSink.debug << "Requested " << *extIt << "\n";
1094     }
1095
1096     if (xfbMode)
1097         infoSink.debug << "in xfb mode\n";
1098
1099     switch (language) {
1100     case EShLangVertex:
1101         break;
1102
1103     case EShLangTessControl:
1104         infoSink.debug << "vertices = " << vertices << "\n";
1105
1106         if (inputPrimitive != ElgNone)
1107             infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
1108         if (vertexSpacing != EvsNone)
1109             infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
1110         if (vertexOrder != EvoNone)
1111             infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
1112         break;
1113
1114     case EShLangTessEvaluation:
1115         infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
1116         infoSink.debug << "vertex spacing = " << TQualifier::getVertexSpacingString(vertexSpacing) << "\n";
1117         infoSink.debug << "triangle order = " << TQualifier::getVertexOrderString(vertexOrder) << "\n";
1118         if (pointMode)
1119             infoSink.debug << "using point mode\n";
1120         break;
1121
1122     case EShLangGeometry:
1123         infoSink.debug << "invocations = " << invocations << "\n";
1124         infoSink.debug << "max_vertices = " << vertices << "\n";
1125         infoSink.debug << "input primitive = " << TQualifier::getGeometryString(inputPrimitive) << "\n";
1126         infoSink.debug << "output primitive = " << TQualifier::getGeometryString(outputPrimitive) << "\n";
1127         break;
1128
1129     case EShLangFragment:
1130         if (pixelCenterInteger)
1131             infoSink.debug << "gl_FragCoord pixel center is integer\n";
1132         if (originUpperLeft)
1133             infoSink.debug << "gl_FragCoord origin is upper left\n";
1134         if (earlyFragmentTests)
1135             infoSink.debug << "using early_fragment_tests\n";
1136         if (postDepthCoverage)
1137             infoSink.debug << "using post_depth_coverage\n";
1138         if (depthLayout != EldNone)
1139             infoSink.debug << "using " << TQualifier::getLayoutDepthString(depthLayout) << "\n";
1140         if (blendEquations != 0) {
1141             infoSink.debug << "using";
1142             // blendEquations is a mask, decode it
1143             for (TBlendEquationShift be = (TBlendEquationShift)0; be < EBlendCount; be = (TBlendEquationShift)(be + 1)) {
1144                 if (blendEquations & (1 << be))
1145                     infoSink.debug << " " << TQualifier::getBlendEquationString(be);
1146             }
1147             infoSink.debug << "\n";
1148         }
1149         break;
1150
1151     case EShLangCompute:
1152         infoSink.debug << "local_size = (" << localSize[0] << ", " << localSize[1] << ", " << localSize[2] << ")\n";
1153         {
1154             if (localSizeSpecId[0] != TQualifier::layoutNotSet ||
1155                 localSizeSpecId[1] != TQualifier::layoutNotSet ||
1156                 localSizeSpecId[2] != TQualifier::layoutNotSet) {
1157                 infoSink.debug << "local_size ids = (" <<
1158                     localSizeSpecId[0] << ", " <<
1159                     localSizeSpecId[1] << ", " <<
1160                     localSizeSpecId[2] << ")\n";
1161             }
1162         }
1163         break;
1164
1165     default:
1166         break;
1167     }
1168
1169     if (treeRoot == 0 || ! tree)
1170         return;
1171
1172     TOutputTraverser it(infoSink);
1173
1174     treeRoot->traverse(&it);
1175 }
1176
1177 } // end namespace glslang