Implement atomic ops, bit conversions, fix fwidth stage mask, fix saturate dest modifier.
[platform/upstream/glslang.git] / glslang / Include / intermediate.h
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 //
38 // Definition of the in-memory high-level intermediate representation
39 // of shaders.  This is a tree that parser creates.
40 //
41 // Nodes in the tree are defined as a hierarchy of classes derived from 
42 // TIntermNode. Each is a node in a tree.  There is no preset branching factor;
43 // each node can have it's own type of list of children.
44 //
45
46 #ifndef __INTERMEDIATE_H
47 #define __INTERMEDIATE_H
48
49 #include "../Include/Common.h"
50 #include "../Include/Types.h"
51 #include "../Include/ConstantUnion.h"
52
53 namespace glslang {
54
55 //
56 // Operators used by the high-level (parse tree) representation.
57 //
58 enum TOperator {
59     EOpNull,            // if in a node, should only mean a node is still being built
60     EOpSequence,        // denotes a list of statements, or parameters, etc.
61     EOpLinkerObjects,   // for aggregate node of objects the linker may need, if not reference by the rest of the AST
62     EOpFunctionCall,    
63     EOpFunction,        // For function definition
64     EOpParameters,      // an aggregate listing the parameters to a function
65
66     //
67     // Unary operators
68     //
69     
70     EOpNegative,
71     EOpLogicalNot,
72     EOpVectorLogicalNot,
73     EOpBitwiseNot,
74
75     EOpPostIncrement,
76     EOpPostDecrement,
77     EOpPreIncrement,
78     EOpPreDecrement,
79
80     EOpConvIntToBool,
81     EOpConvUintToBool,
82     EOpConvFloatToBool,
83     EOpConvDoubleToBool,
84     EOpConvInt64ToBool,
85     EOpConvUint64ToBool,
86     EOpConvBoolToFloat,
87     EOpConvIntToFloat,
88     EOpConvUintToFloat,
89     EOpConvDoubleToFloat,
90     EOpConvInt64ToFloat,
91     EOpConvUint64ToFloat,
92     EOpConvUintToInt,
93     EOpConvFloatToInt,
94     EOpConvBoolToInt,
95     EOpConvDoubleToInt,
96     EOpConvInt64ToInt,
97     EOpConvUint64ToInt,
98     EOpConvIntToUint,
99     EOpConvFloatToUint,
100     EOpConvBoolToUint,
101     EOpConvDoubleToUint,
102     EOpConvInt64ToUint,
103     EOpConvUint64ToUint,
104     EOpConvIntToDouble,
105     EOpConvUintToDouble,
106     EOpConvFloatToDouble,
107     EOpConvBoolToDouble,
108     EOpConvInt64ToDouble,
109     EOpConvUint64ToDouble,
110     EOpConvBoolToInt64,
111     EOpConvIntToInt64,
112     EOpConvUintToInt64,
113     EOpConvFloatToInt64,
114     EOpConvDoubleToInt64,
115     EOpConvUint64ToInt64,
116     EOpConvBoolToUint64,
117     EOpConvIntToUint64,
118     EOpConvUintToUint64,
119     EOpConvFloatToUint64,
120     EOpConvDoubleToUint64,
121     EOpConvInt64ToUint64,
122
123     //
124     // binary operations
125     //
126
127     EOpAdd,
128     EOpSub,
129     EOpMul,
130     EOpDiv,
131     EOpMod,
132     EOpRightShift,
133     EOpLeftShift,
134     EOpAnd,
135     EOpInclusiveOr,
136     EOpExclusiveOr,
137     EOpEqual,
138     EOpNotEqual,
139     EOpVectorEqual,
140     EOpVectorNotEqual,
141     EOpLessThan,
142     EOpGreaterThan,
143     EOpLessThanEqual,
144     EOpGreaterThanEqual,
145     EOpComma,
146
147     EOpVectorTimesScalar,
148     EOpVectorTimesMatrix,
149     EOpMatrixTimesVector,
150     EOpMatrixTimesScalar,
151
152     EOpLogicalOr,
153     EOpLogicalXor,
154     EOpLogicalAnd,
155
156     EOpIndexDirect,
157     EOpIndexIndirect,
158     EOpIndexDirectStruct,
159
160     EOpVectorSwizzle,
161
162     EOpMethod,
163
164     //
165     // Built-in functions mapped to operators
166     //
167
168     EOpRadians,
169     EOpDegrees,
170     EOpSin,
171     EOpCos,
172     EOpTan,
173     EOpAsin,
174     EOpAcos,
175     EOpAtan,
176     EOpSinh,
177     EOpCosh,
178     EOpTanh,
179     EOpAsinh,
180     EOpAcosh,
181     EOpAtanh,
182
183     EOpPow,
184     EOpExp,
185     EOpLog,
186     EOpExp2,
187     EOpLog2,
188     EOpSqrt,
189     EOpInverseSqrt,
190
191     EOpAbs,
192     EOpSign,
193     EOpFloor,
194     EOpTrunc,
195     EOpRound,
196     EOpRoundEven,
197     EOpCeil,
198     EOpFract,
199     EOpModf,
200     EOpMin,
201     EOpMax,
202     EOpClamp,
203     EOpMix,
204     EOpStep,
205     EOpSmoothStep,
206
207     EOpIsNan,
208     EOpIsInf,
209
210     EOpFma,
211
212     EOpFrexp,
213     EOpLdexp,
214
215     EOpFloatBitsToInt,
216     EOpFloatBitsToUint,
217     EOpIntBitsToFloat,
218     EOpUintBitsToFloat,
219     EOpDoubleBitsToInt64,
220     EOpDoubleBitsToUint64,
221     EOpInt64BitsToDouble,
222     EOpUint64BitsToDouble,
223     EOpPackSnorm2x16,
224     EOpUnpackSnorm2x16,
225     EOpPackUnorm2x16,
226     EOpUnpackUnorm2x16,
227     EOpPackSnorm4x8,
228     EOpUnpackSnorm4x8,
229     EOpPackUnorm4x8,
230     EOpUnpackUnorm4x8,
231     EOpPackHalf2x16,
232     EOpUnpackHalf2x16,
233     EOpPackDouble2x32,
234     EOpUnpackDouble2x32,
235     EOpPackInt2x32,
236     EOpUnpackInt2x32,
237     EOpPackUint2x32,
238     EOpUnpackUint2x32,
239
240     EOpLength,
241     EOpDistance,
242     EOpDot,
243     EOpCross,
244     EOpNormalize,
245     EOpFaceForward,
246     EOpReflect,
247     EOpRefract,
248
249     EOpDPdx,            // Fragment only
250     EOpDPdy,            // Fragment only
251     EOpFwidth,          // Fragment only
252     EOpDPdxFine,        // Fragment only
253     EOpDPdyFine,        // Fragment only
254     EOpFwidthFine,      // Fragment only
255     EOpDPdxCoarse,      // Fragment only
256     EOpDPdyCoarse,      // Fragment only
257     EOpFwidthCoarse,    // Fragment only
258
259     EOpInterpolateAtCentroid, // Fragment only
260     EOpInterpolateAtSample,   // Fragment only
261     EOpInterpolateAtOffset,   // Fragment only
262
263     EOpMatrixTimesMatrix,
264     EOpOuterProduct,
265     EOpDeterminant,
266     EOpMatrixInverse,
267     EOpTranspose,
268
269     EOpFtransform,
270
271     EOpNoise,
272
273     EOpEmitVertex,           // geometry only
274     EOpEndPrimitive,         // geometry only
275     EOpEmitStreamVertex,     // geometry only
276     EOpEndStreamPrimitive,   // geometry only
277
278     EOpBarrier,
279     EOpMemoryBarrier,
280     EOpMemoryBarrierAtomicCounter,
281     EOpMemoryBarrierBuffer,
282     EOpMemoryBarrierImage,
283     EOpMemoryBarrierShared,  // compute only
284     EOpGroupMemoryBarrier,   // compute only
285
286     EOpBallot,
287     EOpReadInvocation,
288     EOpReadFirstInvocation,
289
290     EOpAnyInvocation,
291     EOpAllInvocations,
292     EOpAllInvocationsEqual,
293
294     EOpAtomicAdd,
295     EOpAtomicMin,
296     EOpAtomicMax,
297     EOpAtomicAnd,
298     EOpAtomicOr,
299     EOpAtomicXor,
300     EOpAtomicExchange,
301     EOpAtomicCompSwap,
302
303     EOpAtomicCounterIncrement,
304     EOpAtomicCounterDecrement,
305     EOpAtomicCounter,
306
307     EOpAny,
308     EOpAll,
309
310     //
311     // Branch
312     //
313
314     EOpKill,            // Fragment only
315     EOpReturn,
316     EOpBreak,
317     EOpContinue,
318     EOpCase,
319     EOpDefault,
320
321     //
322     // Constructors
323     //
324
325     EOpConstructGuardStart,
326     EOpConstructInt,          // these first scalar forms also identify what implicit conversion is needed
327     EOpConstructUint,
328     EOpConstructInt64,
329     EOpConstructUint64,
330     EOpConstructBool,
331     EOpConstructFloat,
332     EOpConstructDouble,
333     EOpConstructVec2,
334     EOpConstructVec3,
335     EOpConstructVec4,
336     EOpConstructDVec2,
337     EOpConstructDVec3,
338     EOpConstructDVec4,
339     EOpConstructBVec2,
340     EOpConstructBVec3,
341     EOpConstructBVec4,
342     EOpConstructIVec2,
343     EOpConstructIVec3,
344     EOpConstructIVec4,
345     EOpConstructUVec2,
346     EOpConstructUVec3,
347     EOpConstructUVec4,
348     EOpConstructI64Vec2,
349     EOpConstructI64Vec3,
350     EOpConstructI64Vec4,
351     EOpConstructU64Vec2,
352     EOpConstructU64Vec3,
353     EOpConstructU64Vec4,
354     EOpConstructMat2x2,
355     EOpConstructMat2x3,
356     EOpConstructMat2x4,
357     EOpConstructMat3x2,
358     EOpConstructMat3x3,
359     EOpConstructMat3x4,
360     EOpConstructMat4x2,
361     EOpConstructMat4x3,
362     EOpConstructMat4x4,
363     EOpConstructDMat2x2,
364     EOpConstructDMat2x3,
365     EOpConstructDMat2x4,
366     EOpConstructDMat3x2,
367     EOpConstructDMat3x3,
368     EOpConstructDMat3x4,
369     EOpConstructDMat4x2,
370     EOpConstructDMat4x3,
371     EOpConstructDMat4x4,
372     EOpConstructStruct,
373     EOpConstructTextureSampler,
374     EOpConstructGuardEnd,
375
376     //
377     // moves
378     //
379     
380     EOpAssign,
381     EOpAddAssign,
382     EOpSubAssign,
383     EOpMulAssign,
384     EOpVectorTimesMatrixAssign,
385     EOpVectorTimesScalarAssign,
386     EOpMatrixTimesScalarAssign,
387     EOpMatrixTimesMatrixAssign,
388     EOpDivAssign,
389     EOpModAssign,
390     EOpAndAssign,
391     EOpInclusiveOrAssign,
392     EOpExclusiveOrAssign,
393     EOpLeftShiftAssign,
394     EOpRightShiftAssign,
395
396     //
397     // Array operators
398     //
399
400     EOpArrayLength,      // "Array" distinguishes from length(v) built-in function, but it applies to vectors and matrices as well.
401
402     //
403     // Image operations
404     //
405
406     EOpImageGuardBegin,
407
408     EOpImageQuerySize,
409     EOpImageQuerySamples,
410     EOpImageLoad,
411     EOpImageStore,
412     EOpImageAtomicAdd,
413     EOpImageAtomicMin,
414     EOpImageAtomicMax,
415     EOpImageAtomicAnd,
416     EOpImageAtomicOr,
417     EOpImageAtomicXor,
418     EOpImageAtomicExchange,
419     EOpImageAtomicCompSwap,
420
421     EOpSubpassLoad,
422     EOpSubpassLoadMS,
423     EOpSparseImageLoad,
424
425     EOpImageGuardEnd,
426
427     //
428     // Texture operations
429     //
430
431     EOpTextureGuardBegin,
432
433     EOpTextureQuerySize,
434     EOpTextureQueryLod,
435     EOpTextureQueryLevels,
436     EOpTextureQuerySamples,
437     EOpTexture,
438     EOpTextureProj,
439     EOpTextureLod,
440     EOpTextureOffset,
441     EOpTextureFetch,
442     EOpTextureFetchOffset,
443     EOpTextureProjOffset,
444     EOpTextureLodOffset,
445     EOpTextureProjLod,
446     EOpTextureProjLodOffset,
447     EOpTextureGrad,
448     EOpTextureGradOffset,
449     EOpTextureProjGrad,
450     EOpTextureProjGradOffset,
451     EOpTextureGather,
452     EOpTextureGatherOffset,
453     EOpTextureGatherOffsets,
454     EOpTextureClamp,
455     EOpTextureOffsetClamp,
456     EOpTextureGradClamp,
457     EOpTextureGradOffsetClamp,
458
459     EOpSparseTextureGuardBegin,
460
461     EOpSparseTexture,
462     EOpSparseTextureLod,
463     EOpSparseTextureOffset,
464     EOpSparseTextureFetch,
465     EOpSparseTextureFetchOffset,
466     EOpSparseTextureLodOffset,
467     EOpSparseTextureGrad,
468     EOpSparseTextureGradOffset,
469     EOpSparseTextureGather,
470     EOpSparseTextureGatherOffset,
471     EOpSparseTextureGatherOffsets,
472     EOpSparseTexelsResident,
473     EOpSparseTextureClamp,
474     EOpSparseTextureOffsetClamp,
475     EOpSparseTextureGradClamp,
476     EOpSparseTextureGradOffsetClamp,
477
478     EOpSparseTextureGuardEnd,
479
480     EOpTextureGuardEnd,
481
482     //
483     // Integer operations
484     //
485
486     EOpAddCarry,
487     EOpSubBorrow,
488     EOpUMulExtended,
489     EOpIMulExtended,
490     EOpBitfieldExtract,
491     EOpBitfieldInsert,
492     EOpBitFieldReverse,
493     EOpBitCount,
494     EOpFindLSB,
495     EOpFindMSB,
496
497     //
498     // HLSL operations
499     //
500
501     EOpClip,                // discard if input value < 0
502     EOpIsFinite,
503     EOpLog10,               // base 10 log
504     EOpRcp,                 // 1/x
505     EOpSaturate,            // clamp from 0 to 1
506     EOpSinCos,              // sin and cos in out parameters
507     EOpGenMul,              // mul(x,y) on any of mat/vec/scalars
508     EOpDst,                 // x = 1, y=src0.y * src1.y, z=src0.z, w=src1.w
509     EOpInterlockedAdd,      // atomic ops, but uses [optional] out arg instead of return
510     EOpInterlockedAnd,      // ...
511     EOpInterlockedCompareExchange, // ...
512     EOpInterlockedCompareStore,    // ...
513     EOpInterlockedExchange, // ...
514     EOpInterlockedMax,      // ...
515     EOpInterlockedMin,      // ...
516     EOpInterlockedOr,       // ...
517     EOpInterlockedXor,      // ...
518
519 };
520
521 class TIntermTraverser;
522 class TIntermOperator;
523 class TIntermAggregate;
524 class TIntermUnary;
525 class TIntermBinary;
526 class TIntermConstantUnion;
527 class TIntermSelection;
528 class TIntermSwitch;
529 class TIntermBranch;
530 class TIntermTyped;
531 class TIntermMethod;
532 class TIntermSymbol;
533
534 } // end namespace glslang
535
536 //
537 // Base class for the tree nodes
538 //
539 // (Put outside the glslang namespace, as it's used as part of the external interface.)
540 //
541 class TIntermNode {
542 public:
543     POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
544
545     TIntermNode() { loc.init(); }
546     virtual const glslang::TSourceLoc& getLoc() const { return loc; }
547     virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; }
548     virtual void traverse(glslang::TIntermTraverser*) = 0;
549     virtual       glslang::TIntermTyped*         getAsTyped()               { return 0; }
550     virtual       glslang::TIntermOperator*      getAsOperator()            { return 0; }
551     virtual       glslang::TIntermConstantUnion* getAsConstantUnion()       { return 0; }
552     virtual       glslang::TIntermAggregate*     getAsAggregate()           { return 0; }
553     virtual       glslang::TIntermUnary*         getAsUnaryNode()           { return 0; }
554     virtual       glslang::TIntermBinary*        getAsBinaryNode()          { return 0; }
555     virtual       glslang::TIntermSelection*     getAsSelectionNode()       { return 0; }
556     virtual       glslang::TIntermSwitch*        getAsSwitchNode()          { return 0; }
557     virtual       glslang::TIntermMethod*        getAsMethodNode()          { return 0; }
558     virtual       glslang::TIntermSymbol*        getAsSymbolNode()          { return 0; }
559     virtual       glslang::TIntermBranch*        getAsBranchNode()          { return 0; }
560
561     virtual const glslang::TIntermTyped*         getAsTyped()         const { return 0; }
562     virtual const glslang::TIntermOperator*      getAsOperator()      const { return 0; }
563     virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; }
564     virtual const glslang::TIntermAggregate*     getAsAggregate()     const { return 0; }
565     virtual const glslang::TIntermUnary*         getAsUnaryNode()     const { return 0; }
566     virtual const glslang::TIntermBinary*        getAsBinaryNode()    const { return 0; }
567     virtual const glslang::TIntermSelection*     getAsSelectionNode() const { return 0; }
568     virtual const glslang::TIntermSwitch*        getAsSwitchNode()    const { return 0; }
569     virtual const glslang::TIntermMethod*        getAsMethodNode()    const { return 0; }
570     virtual const glslang::TIntermSymbol*        getAsSymbolNode()    const { return 0; }
571     virtual const glslang::TIntermBranch*        getAsBranchNode()    const { return 0; }
572     virtual ~TIntermNode() { }
573 protected:
574     glslang::TSourceLoc loc;
575 };
576
577 namespace glslang {
578
579 //
580 // This is just to help yacc.
581 //
582 struct TIntermNodePair {
583     TIntermNode* node1;
584     TIntermNode* node2;
585 };
586
587 //
588 // Intermediate class for nodes that have a type.
589 //
590 class TIntermTyped : public TIntermNode {
591 public:
592     TIntermTyped(const TType& t) { type.shallowCopy(t); }
593     TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); }
594     virtual       TIntermTyped* getAsTyped()       { return this; }
595     virtual const TIntermTyped* getAsTyped() const { return this; }
596     virtual void setType(const TType& t) { type.shallowCopy(t); }
597     virtual const TType& getType() const { return type; }
598     virtual TType& getWritableType() { return type; }
599     
600     virtual TBasicType getBasicType() const { return type.getBasicType(); }
601     virtual TQualifier& getQualifier() { return type.getQualifier(); }
602     virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
603     virtual void propagatePrecision(TPrecisionQualifier);
604     virtual int getVectorSize() const { return type.getVectorSize(); }
605     virtual int getMatrixCols() const { return type.getMatrixCols(); }
606     virtual int getMatrixRows() const { return type.getMatrixRows(); }
607     virtual bool isMatrix() const { return type.isMatrix(); }
608     virtual bool isArray()  const { return type.isArray(); }
609     virtual bool isVector() const { return type.isVector(); }
610     virtual bool isScalar() const { return type.isScalar(); }
611     virtual bool isStruct() const { return type.isStruct(); }
612     TString getCompleteString() const { return type.getCompleteString(); }
613
614 protected:
615     TType type;
616 };
617
618 //
619 // Handle for, do-while, and while loops.
620 //
621 class TIntermLoop : public TIntermNode {
622 public:
623     TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : 
624         body(aBody),
625         test(aTest),
626         terminal(aTerminal),
627         first(testFirst) { }
628     virtual void traverse(TIntermTraverser*);
629     TIntermNode*  getBody() const { return body; }
630     TIntermTyped* getTest() const { return test; }
631     TIntermTyped* getTerminal() const { return terminal; }
632     bool testFirst() const { return first; }
633 protected:
634     TIntermNode* body;       // code to loop over
635     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
636     TIntermTyped* terminal;  // exists for for-loops
637     bool first;              // true for while and for, not for do-while
638 };
639
640 //
641 // Handle case, break, continue, return, and kill.
642 //
643 class TIntermBranch : public TIntermNode {
644 public:
645     TIntermBranch(TOperator op, TIntermTyped* e) :
646         flowOp(op),
647         expression(e) { }
648     virtual       TIntermBranch* getAsBranchNode()       { return this; }
649     virtual const TIntermBranch* getAsBranchNode() const { return this; }
650     virtual void traverse(TIntermTraverser*);
651     TOperator getFlowOp() const { return flowOp; }
652     TIntermTyped* getExpression() const { return expression; }
653 protected:
654     TOperator flowOp;
655     TIntermTyped* expression;
656 };
657
658 //
659 // Represent method names before seeing their calling signature
660 // or resolving them to operations.  Just an expression as the base object
661 // and a textural name.
662 //
663 class TIntermMethod : public TIntermTyped {
664 public:
665     TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { }
666     virtual       TIntermMethod* getAsMethodNode()       { return this; }
667     virtual const TIntermMethod* getAsMethodNode() const { return this; }
668     virtual const TString& getMethodName() const { return method; }
669     virtual TIntermTyped* getObject() const { return object; }
670     virtual void traverse(TIntermTraverser*);
671 protected:
672     TIntermTyped* object;
673     TString method;
674 };
675
676 //
677 // Nodes that correspond to symbols or constants in the source code.
678 //
679 class TIntermSymbol : public TIntermTyped {
680 public:
681     // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
682     // per process threadPoolAllocator, then it causes increased memory usage per compile
683     // it is essential to use "symbol = sym" to assign to symbol
684     TIntermSymbol(int i, const TString& n, const TType& t)
685         : TIntermTyped(t), id(i), constSubtree(nullptr)
686           { name = n; }
687     virtual int getId() const { return id; }
688     virtual const TString& getName() const { return name; }
689     virtual void traverse(TIntermTraverser*);
690     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
691     virtual const TIntermSymbol* getAsSymbolNode() const { return this; }
692     void setConstArray(const TConstUnionArray& c) { constArray = c; }
693     const TConstUnionArray& getConstArray() const { return constArray; }
694     void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
695     TIntermTyped* getConstSubtree() const { return constSubtree; }
696 protected:
697     int id;                      // the unique id of the symbol this node represents
698     TString name;                // the name of the symbol this node represents
699     TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value
700     TIntermTyped* constSubtree;
701 };
702
703 class TIntermConstantUnion : public TIntermTyped {
704 public:
705     TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { }
706     const TConstUnionArray& getConstArray() const { return constArray; }
707     virtual       TIntermConstantUnion* getAsConstantUnion()       { return this; }
708     virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
709     virtual void traverse(TIntermTraverser*);
710     virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
711     virtual TIntermTyped* fold(TOperator, const TType&) const;
712     void setLiteral() { literal = true; }
713     void setExpression() { literal = false; }
714     bool isLiteral() const { return literal; }
715 protected:
716     const TConstUnionArray constArray;
717     bool literal;  // true if node represents a literal in the source code
718 };
719
720 // Represent the independent aspects of a texturing TOperator
721 struct TCrackedTextureOp {
722     bool query;
723     bool proj;
724     bool lod;
725     bool fetch;
726     bool offset;
727     bool offsets;
728     bool gather;
729     bool grad;
730     bool subpass;
731     bool lodClamp;
732 };
733
734 //
735 // Intermediate class for node types that hold operators.
736 //
737 class TIntermOperator : public TIntermTyped {
738 public:
739     virtual       TIntermOperator* getAsOperator()       { return this; }
740     virtual const TIntermOperator* getAsOperator() const { return this; }
741     TOperator getOp() const { return op; }
742     virtual bool promote() { return true; }
743     bool modifiesState() const;
744     bool isConstructor() const;
745     bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; }
746     bool isImage()   const { return op > EOpImageGuardBegin   && op < EOpImageGuardEnd; }
747     bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
748     bool isSparseImage()   const { return op == EOpSparseImageLoad; }
749
750     // Crack the op into the individual dimensions of texturing operation.
751     void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const
752     {
753         cracked.query = false;
754         cracked.proj = false;
755         cracked.lod = false;
756         cracked.fetch = false;
757         cracked.offset = false;
758         cracked.offsets = false;
759         cracked.gather = false;
760         cracked.grad = false;
761         cracked.subpass = false;
762         cracked.lodClamp = false;
763
764         switch (op) {
765         case EOpImageQuerySize:
766         case EOpImageQuerySamples:
767         case EOpTextureQuerySize:
768         case EOpTextureQueryLod:
769         case EOpTextureQueryLevels:
770         case EOpTextureQuerySamples:
771         case EOpSparseTexelsResident:
772             cracked.query = true;
773             break;
774         case EOpTexture:
775         case EOpSparseTexture:
776             break;
777         case EOpTextureClamp:
778         case EOpSparseTextureClamp:
779             cracked.lodClamp = true;
780             break;
781         case EOpTextureProj:
782             cracked.proj = true;
783             break;
784         case EOpTextureLod:
785         case EOpSparseTextureLod:
786             cracked.lod = true;
787             break;
788         case EOpTextureOffset:
789         case EOpSparseTextureOffset:
790             cracked.offset = true;
791             break;
792         case EOpTextureOffsetClamp:
793         case EOpSparseTextureOffsetClamp:
794             cracked.offset = true;
795             cracked.lodClamp = true;
796             break;
797         case EOpTextureFetch:
798         case EOpSparseTextureFetch:
799             cracked.fetch = true;
800             if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D)
801                 cracked.lod = true;
802             break;
803         case EOpTextureFetchOffset:
804         case EOpSparseTextureFetchOffset:
805             cracked.fetch = true;
806             cracked.offset = true;
807             if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D)
808                 cracked.lod = true;
809             break;
810         case EOpTextureProjOffset:
811             cracked.offset = true;
812             cracked.proj = true;
813             break;
814         case EOpTextureLodOffset:
815         case EOpSparseTextureLodOffset:
816             cracked.offset = true;
817             cracked.lod = true;
818             break;
819         case EOpTextureProjLod:
820             cracked.lod = true;
821             cracked.proj = true;
822             break;
823         case EOpTextureProjLodOffset:
824             cracked.offset = true;
825             cracked.lod = true;
826             cracked.proj = true;
827             break;
828         case EOpTextureGrad:
829         case EOpSparseTextureGrad:
830             cracked.grad = true;
831             break;
832         case EOpTextureGradClamp:
833         case EOpSparseTextureGradClamp:
834             cracked.grad = true;
835             cracked.lodClamp = true;
836             break;
837         case EOpTextureGradOffset:
838         case EOpSparseTextureGradOffset:
839             cracked.grad = true;
840             cracked.offset = true;
841             break;
842         case EOpTextureProjGrad:
843             cracked.grad = true;
844             cracked.proj = true;
845             break;
846         case EOpTextureProjGradOffset:
847             cracked.grad = true;
848             cracked.offset = true;
849             cracked.proj = true;
850             break;
851         case EOpTextureGradOffsetClamp:
852         case EOpSparseTextureGradOffsetClamp:
853             cracked.grad = true;
854             cracked.offset = true;
855             cracked.lodClamp = true;
856             break;
857         case EOpTextureGather:
858         case EOpSparseTextureGather:
859             cracked.gather = true;
860             break;
861         case EOpTextureGatherOffset:
862         case EOpSparseTextureGatherOffset:
863             cracked.gather = true;
864             cracked.offset = true;
865             break;
866         case EOpTextureGatherOffsets:
867         case EOpSparseTextureGatherOffsets:
868             cracked.gather = true;
869             cracked.offsets = true;
870             break;
871         case EOpSubpassLoad:
872         case EOpSubpassLoadMS:
873             cracked.subpass = true;
874             break;
875         default:
876             break;
877         }
878     }
879
880 protected:
881     TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o) {}
882     TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
883     TOperator op;
884 };
885
886 //
887 // Nodes for all the basic binary math operators.
888 //
889 class TIntermBinary : public TIntermOperator {
890 public:
891     TIntermBinary(TOperator o) : TIntermOperator(o) {}
892     virtual void traverse(TIntermTraverser*);
893     virtual void setLeft(TIntermTyped* n) { left = n; }
894     virtual void setRight(TIntermTyped* n) { right = n; }
895     virtual TIntermTyped* getLeft() const { return left; }
896     virtual TIntermTyped* getRight() const { return right; }
897     virtual       TIntermBinary* getAsBinaryNode()       { return this; }
898     virtual const TIntermBinary* getAsBinaryNode() const { return this; }
899     virtual bool promote();
900     virtual void updatePrecision();
901 protected:
902     TIntermTyped* left;
903     TIntermTyped* right;
904 };
905
906 //
907 // Nodes for unary math operators.
908 //
909 class TIntermUnary : public TIntermOperator {
910 public:
911     TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
912     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
913     virtual void traverse(TIntermTraverser*);
914     virtual void setOperand(TIntermTyped* o) { operand = o; }
915     virtual       TIntermTyped* getOperand() { return operand; }
916     virtual const TIntermTyped* getOperand() const { return operand; }
917     virtual       TIntermUnary* getAsUnaryNode()       { return this; }
918     virtual const TIntermUnary* getAsUnaryNode() const { return this; }
919     virtual bool promote();
920     virtual void updatePrecision();
921 protected:
922     TIntermTyped* operand;
923 };
924
925 typedef TVector<TIntermNode*> TIntermSequence;
926 typedef TVector<int> TQualifierList;
927 //
928 // Nodes that operate on an arbitrary sized set of children.
929 //
930 class TIntermAggregate : public TIntermOperator {
931 public:
932     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
933     TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
934     ~TIntermAggregate() { delete pragmaTable; }
935     virtual       TIntermAggregate* getAsAggregate()       { return this; }
936     virtual const TIntermAggregate* getAsAggregate() const { return this; }
937     virtual void setOperator(TOperator o) { op = o; }
938     virtual       TIntermSequence& getSequence()       { return sequence; }
939     virtual const TIntermSequence& getSequence() const { return sequence; }
940     virtual void setName(const TString& n) { name = n; }
941     virtual const TString& getName() const { return name; }
942     virtual void traverse(TIntermTraverser*);
943     virtual void setUserDefined() { userDefined = true; }
944     virtual bool isUserDefined() { return userDefined; }
945     virtual TQualifierList& getQualifierList() { return qualifier; }
946     virtual const TQualifierList& getQualifierList() const { return qualifier; }
947     void setOptimize(bool o) { optimize = o; }
948     void setDebug(bool d) { debug = d; }
949     bool getOptimize() const { return optimize; }
950     bool getDebug() const { return debug; }
951     void addToPragmaTable(const TPragmaTable& pTable);
952     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
953 protected:
954     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
955     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
956     TIntermSequence sequence;
957     TQualifierList qualifier;
958     TString name;
959     bool userDefined; // used for user defined function names
960     bool optimize;
961     bool debug;
962     TPragmaTable* pragmaTable;
963 };
964
965 //
966 // For if tests.
967 //
968 class TIntermSelection : public TIntermTyped {
969 public:
970     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
971         TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
972     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
973         TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
974     virtual void traverse(TIntermTraverser*);
975     virtual TIntermTyped* getCondition() const { return condition; }
976     virtual TIntermNode* getTrueBlock() const { return trueBlock; }
977     virtual TIntermNode* getFalseBlock() const { return falseBlock; }
978     virtual       TIntermSelection* getAsSelectionNode()       { return this; }
979     virtual const TIntermSelection* getAsSelectionNode() const { return this; }
980 protected:
981     TIntermTyped* condition;
982     TIntermNode* trueBlock;
983     TIntermNode* falseBlock;
984 };
985
986 //
987 // For switch statements.  Designed use is that a switch will have sequence of nodes
988 // that are either case/default nodes or a *single* node that represents all the code
989 // in between (if any) consecutive case/defaults.  So, a traversal need only deal with
990 // 0 or 1 nodes per case/default statement.
991 //
992 class TIntermSwitch : public TIntermNode {
993 public:
994     TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b) { }
995     virtual void traverse(TIntermTraverser*);
996     virtual TIntermNode* getCondition() const { return condition; }
997     virtual TIntermAggregate* getBody() const { return body; }
998     virtual       TIntermSwitch* getAsSwitchNode()       { return this; }
999     virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
1000 protected:
1001     TIntermTyped* condition;
1002     TIntermAggregate* body;
1003 };
1004
1005 enum TVisit
1006 {
1007     EvPreVisit,
1008     EvInVisit,
1009     EvPostVisit
1010 };
1011
1012 //
1013 // For traversing the tree.  User should derive from this, 
1014 // put their traversal specific data in it, and then pass
1015 // it to a Traverse method.
1016 //
1017 // When using this, just fill in the methods for nodes you want visited.
1018 // Return false from a pre-visit to skip visiting that node's subtree.
1019 //
1020 // Explicitly set postVisit to true if you want post visiting, otherwise,
1021 // filled in methods will only be called at pre-visit time (before processing
1022 // the subtree).  Similarly for inVisit for in-order visiting of nodes with
1023 // multiple children.
1024 //
1025 // If you only want post-visits, explicitly turn off preVisit (and inVisit) 
1026 // and turn on postVisit.
1027 //
1028 // In general, for the visit*() methods, return true from interior nodes 
1029 // to have the traversal continue on to children.
1030 //
1031 // If you process children yourself, or don't want them processed, return false.
1032 //
1033 class TIntermTraverser {
1034 public:
1035     POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
1036     TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
1037             preVisit(preVisit),
1038             inVisit(inVisit),
1039             postVisit(postVisit),
1040             rightToLeft(rightToLeft),
1041             depth(0),
1042             maxDepth(0) { }
1043     virtual ~TIntermTraverser() { }
1044
1045     virtual void visitSymbol(TIntermSymbol*)               { }
1046     virtual void visitConstantUnion(TIntermConstantUnion*) { }
1047     virtual bool visitBinary(TVisit, TIntermBinary*)       { return true; }
1048     virtual bool visitUnary(TVisit, TIntermUnary*)         { return true; }
1049     virtual bool visitSelection(TVisit, TIntermSelection*) { return true; }
1050     virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; }
1051     virtual bool visitLoop(TVisit, TIntermLoop*)           { return true; }
1052     virtual bool visitBranch(TVisit, TIntermBranch*)       { return true; }
1053     virtual bool visitSwitch(TVisit, TIntermSwitch*)       { return true; }
1054
1055     int getMaxDepth() const { return maxDepth; }
1056
1057     void incrementDepth(TIntermNode *current)
1058     {
1059         depth++;
1060         maxDepth = (std::max)(maxDepth, depth);
1061         path.push_back(current);
1062     }
1063
1064     void decrementDepth()
1065     {
1066         depth--;
1067         path.pop_back();
1068     }
1069
1070     TIntermNode *getParentNode()
1071     {
1072         return path.size() == 0 ? NULL : path.back();
1073     }
1074
1075     const bool preVisit;
1076     const bool inVisit;
1077     const bool postVisit;
1078     const bool rightToLeft;
1079
1080 protected:
1081     TIntermTraverser& operator=(TIntermTraverser&);
1082
1083     int depth;
1084     int maxDepth;
1085
1086     // All the nodes from root to the current node's parent during traversing.
1087     TVector<TIntermNode *> path;
1088 };
1089
1090 // KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if
1091 // sized with the same symbol, involving no operations"
1092 inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2)
1093 {
1094     return node1->getAsSymbolNode() && node2->getAsSymbolNode() &&
1095            node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId();
1096 }
1097
1098 } // end namespace glslang
1099
1100 #endif // __INTERMEDIATE_H