1759c86730128ae6516e2a9e1efe8fddb4e13fed
[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,
502     EOpIsFinite,
503     EOpLog10,
504     EOpRcp,
505     EOpSaturate,
506     EOpSinCos,
507     EOpGenMul,  // mul(x,y) on any of mat/vec/scalars
508     EOpDst,
509 };
510
511 class TIntermTraverser;
512 class TIntermOperator;
513 class TIntermAggregate;
514 class TIntermUnary;
515 class TIntermBinary;
516 class TIntermConstantUnion;
517 class TIntermSelection;
518 class TIntermSwitch;
519 class TIntermBranch;
520 class TIntermTyped;
521 class TIntermMethod;
522 class TIntermSymbol;
523
524 } // end namespace glslang
525
526 //
527 // Base class for the tree nodes
528 //
529 // (Put outside the glslang namespace, as it's used as part of the external interface.)
530 //
531 class TIntermNode {
532 public:
533     POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
534
535     TIntermNode() { loc.init(); }
536     virtual const glslang::TSourceLoc& getLoc() const { return loc; }
537     virtual void setLoc(const glslang::TSourceLoc& l) { loc = l; }
538     virtual void traverse(glslang::TIntermTraverser*) = 0;
539     virtual       glslang::TIntermTyped*         getAsTyped()               { return 0; }
540     virtual       glslang::TIntermOperator*      getAsOperator()            { return 0; }
541     virtual       glslang::TIntermConstantUnion* getAsConstantUnion()       { return 0; }
542     virtual       glslang::TIntermAggregate*     getAsAggregate()           { return 0; }
543     virtual       glslang::TIntermUnary*         getAsUnaryNode()           { return 0; }
544     virtual       glslang::TIntermBinary*        getAsBinaryNode()          { return 0; }
545     virtual       glslang::TIntermSelection*     getAsSelectionNode()       { return 0; }
546     virtual       glslang::TIntermSwitch*        getAsSwitchNode()          { return 0; }
547     virtual       glslang::TIntermMethod*        getAsMethodNode()          { return 0; }
548     virtual       glslang::TIntermSymbol*        getAsSymbolNode()          { return 0; }
549     virtual       glslang::TIntermBranch*        getAsBranchNode()          { return 0; }
550
551     virtual const glslang::TIntermTyped*         getAsTyped()         const { return 0; }
552     virtual const glslang::TIntermOperator*      getAsOperator()      const { return 0; }
553     virtual const glslang::TIntermConstantUnion* getAsConstantUnion() const { return 0; }
554     virtual const glslang::TIntermAggregate*     getAsAggregate()     const { return 0; }
555     virtual const glslang::TIntermUnary*         getAsUnaryNode()     const { return 0; }
556     virtual const glslang::TIntermBinary*        getAsBinaryNode()    const { return 0; }
557     virtual const glslang::TIntermSelection*     getAsSelectionNode() const { return 0; }
558     virtual const glslang::TIntermSwitch*        getAsSwitchNode()    const { return 0; }
559     virtual const glslang::TIntermMethod*        getAsMethodNode()    const { return 0; }
560     virtual const glslang::TIntermSymbol*        getAsSymbolNode()    const { return 0; }
561     virtual const glslang::TIntermBranch*        getAsBranchNode()    const { return 0; }
562     virtual ~TIntermNode() { }
563 protected:
564     glslang::TSourceLoc loc;
565 };
566
567 namespace glslang {
568
569 //
570 // This is just to help yacc.
571 //
572 struct TIntermNodePair {
573     TIntermNode* node1;
574     TIntermNode* node2;
575 };
576
577 //
578 // Intermediate class for nodes that have a type.
579 //
580 class TIntermTyped : public TIntermNode {
581 public:
582     TIntermTyped(const TType& t) { type.shallowCopy(t); }
583     TIntermTyped(TBasicType basicType) { TType bt(basicType); type.shallowCopy(bt); }
584     virtual       TIntermTyped* getAsTyped()       { return this; }
585     virtual const TIntermTyped* getAsTyped() const { return this; }
586     virtual void setType(const TType& t) { type.shallowCopy(t); }
587     virtual const TType& getType() const { return type; }
588     virtual TType& getWritableType() { return type; }
589     
590     virtual TBasicType getBasicType() const { return type.getBasicType(); }
591     virtual TQualifier& getQualifier() { return type.getQualifier(); }
592     virtual const TQualifier& getQualifier() const { return type.getQualifier(); }
593     virtual void propagatePrecision(TPrecisionQualifier);
594     virtual int getVectorSize() const { return type.getVectorSize(); }
595     virtual int getMatrixCols() const { return type.getMatrixCols(); }
596     virtual int getMatrixRows() const { return type.getMatrixRows(); }
597     virtual bool isMatrix() const { return type.isMatrix(); }
598     virtual bool isArray()  const { return type.isArray(); }
599     virtual bool isVector() const { return type.isVector(); }
600     virtual bool isScalar() const { return type.isScalar(); }
601     virtual bool isStruct() const { return type.isStruct(); }
602     TString getCompleteString() const { return type.getCompleteString(); }
603
604 protected:
605     TType type;
606 };
607
608 //
609 // Handle for, do-while, and while loops.
610 //
611 class TIntermLoop : public TIntermNode {
612 public:
613     TIntermLoop(TIntermNode* aBody, TIntermTyped* aTest, TIntermTyped* aTerminal, bool testFirst) : 
614         body(aBody),
615         test(aTest),
616         terminal(aTerminal),
617         first(testFirst) { }
618     virtual void traverse(TIntermTraverser*);
619     TIntermNode*  getBody() const { return body; }
620     TIntermTyped* getTest() const { return test; }
621     TIntermTyped* getTerminal() const { return terminal; }
622     bool testFirst() const { return first; }
623 protected:
624     TIntermNode* body;       // code to loop over
625     TIntermTyped* test;      // exit condition associated with loop, could be 0 for 'for' loops
626     TIntermTyped* terminal;  // exists for for-loops
627     bool first;              // true for while and for, not for do-while
628 };
629
630 //
631 // Handle case, break, continue, return, and kill.
632 //
633 class TIntermBranch : public TIntermNode {
634 public:
635     TIntermBranch(TOperator op, TIntermTyped* e) :
636         flowOp(op),
637         expression(e) { }
638     virtual       TIntermBranch* getAsBranchNode()       { return this; }
639     virtual const TIntermBranch* getAsBranchNode() const { return this; }
640     virtual void traverse(TIntermTraverser*);
641     TOperator getFlowOp() const { return flowOp; }
642     TIntermTyped* getExpression() const { return expression; }
643 protected:
644     TOperator flowOp;
645     TIntermTyped* expression;
646 };
647
648 //
649 // Represent method names before seeing their calling signature
650 // or resolving them to operations.  Just an expression as the base object
651 // and a textural name.
652 //
653 class TIntermMethod : public TIntermTyped {
654 public:
655     TIntermMethod(TIntermTyped* o, const TType& t, const TString& m) : TIntermTyped(t), object(o), method(m) { }
656     virtual       TIntermMethod* getAsMethodNode()       { return this; }
657     virtual const TIntermMethod* getAsMethodNode() const { return this; }
658     virtual const TString& getMethodName() const { return method; }
659     virtual TIntermTyped* getObject() const { return object; }
660     virtual void traverse(TIntermTraverser*);
661 protected:
662     TIntermTyped* object;
663     TString method;
664 };
665
666 //
667 // Nodes that correspond to symbols or constants in the source code.
668 //
669 class TIntermSymbol : public TIntermTyped {
670 public:
671     // if symbol is initialized as symbol(sym), the memory comes from the pool allocator of sym. If sym comes from
672     // per process threadPoolAllocator, then it causes increased memory usage per compile
673     // it is essential to use "symbol = sym" to assign to symbol
674     TIntermSymbol(int i, const TString& n, const TType& t)
675         : TIntermTyped(t), id(i), constSubtree(nullptr)
676           { name = n; }
677     virtual int getId() const { return id; }
678     virtual const TString& getName() const { return name; }
679     virtual void traverse(TIntermTraverser*);
680     virtual       TIntermSymbol* getAsSymbolNode()       { return this; }
681     virtual const TIntermSymbol* getAsSymbolNode() const { return this; }
682     void setConstArray(const TConstUnionArray& c) { constArray = c; }
683     const TConstUnionArray& getConstArray() const { return constArray; }
684     void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
685     TIntermTyped* getConstSubtree() const { return constSubtree; }
686 protected:
687     int id;                      // the unique id of the symbol this node represents
688     TString name;                // the name of the symbol this node represents
689     TConstUnionArray constArray; // if the symbol is a front-end compile-time constant, this is its value
690     TIntermTyped* constSubtree;
691 };
692
693 class TIntermConstantUnion : public TIntermTyped {
694 public:
695     TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), constArray(ua), literal(false) { }
696     const TConstUnionArray& getConstArray() const { return constArray; }
697     virtual       TIntermConstantUnion* getAsConstantUnion()       { return this; }
698     virtual const TIntermConstantUnion* getAsConstantUnion() const { return this; }
699     virtual void traverse(TIntermTraverser*);
700     virtual TIntermTyped* fold(TOperator, const TIntermTyped*) const;
701     virtual TIntermTyped* fold(TOperator, const TType&) const;
702     void setLiteral() { literal = true; }
703     void setExpression() { literal = false; }
704     bool isLiteral() const { return literal; }
705 protected:
706     const TConstUnionArray constArray;
707     bool literal;  // true if node represents a literal in the source code
708 };
709
710 // Represent the independent aspects of a texturing TOperator
711 struct TCrackedTextureOp {
712     bool query;
713     bool proj;
714     bool lod;
715     bool fetch;
716     bool offset;
717     bool offsets;
718     bool gather;
719     bool grad;
720     bool subpass;
721     bool lodClamp;
722 };
723
724 //
725 // Intermediate class for node types that hold operators.
726 //
727 class TIntermOperator : public TIntermTyped {
728 public:
729     virtual       TIntermOperator* getAsOperator()       { return this; }
730     virtual const TIntermOperator* getAsOperator() const { return this; }
731     TOperator getOp() const { return op; }
732     virtual bool promote() { return true; }
733     bool modifiesState() const;
734     bool isConstructor() const;
735     bool isTexture() const { return op > EOpTextureGuardBegin && op < EOpTextureGuardEnd; }
736     bool isImage()   const { return op > EOpImageGuardBegin   && op < EOpImageGuardEnd; }
737     bool isSparseTexture() const { return op > EOpSparseTextureGuardBegin && op < EOpSparseTextureGuardEnd; }
738     bool isSparseImage()   const { return op == EOpSparseImageLoad; }
739
740     // Crack the op into the individual dimensions of texturing operation.
741     void crackTexture(TSampler sampler, TCrackedTextureOp& cracked) const
742     {
743         cracked.query = false;
744         cracked.proj = false;
745         cracked.lod = false;
746         cracked.fetch = false;
747         cracked.offset = false;
748         cracked.offsets = false;
749         cracked.gather = false;
750         cracked.grad = false;
751         cracked.subpass = false;
752         cracked.lodClamp = false;
753
754         switch (op) {
755         case EOpImageQuerySize:
756         case EOpImageQuerySamples:
757         case EOpTextureQuerySize:
758         case EOpTextureQueryLod:
759         case EOpTextureQueryLevels:
760         case EOpTextureQuerySamples:
761         case EOpSparseTexelsResident:
762             cracked.query = true;
763             break;
764         case EOpTexture:
765         case EOpSparseTexture:
766             break;
767         case EOpTextureClamp:
768         case EOpSparseTextureClamp:
769             cracked.lodClamp = true;
770             break;
771         case EOpTextureProj:
772             cracked.proj = true;
773             break;
774         case EOpTextureLod:
775         case EOpSparseTextureLod:
776             cracked.lod = true;
777             break;
778         case EOpTextureOffset:
779         case EOpSparseTextureOffset:
780             cracked.offset = true;
781             break;
782         case EOpTextureOffsetClamp:
783         case EOpSparseTextureOffsetClamp:
784             cracked.offset = true;
785             cracked.lodClamp = true;
786             break;
787         case EOpTextureFetch:
788         case EOpSparseTextureFetch:
789             cracked.fetch = true;
790             if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D)
791                 cracked.lod = true;
792             break;
793         case EOpTextureFetchOffset:
794         case EOpSparseTextureFetchOffset:
795             cracked.fetch = true;
796             cracked.offset = true;
797             if (sampler.dim == Esd1D || (sampler.dim == Esd2D && ! sampler.ms) || sampler.dim == Esd3D)
798                 cracked.lod = true;
799             break;
800         case EOpTextureProjOffset:
801             cracked.offset = true;
802             cracked.proj = true;
803             break;
804         case EOpTextureLodOffset:
805         case EOpSparseTextureLodOffset:
806             cracked.offset = true;
807             cracked.lod = true;
808             break;
809         case EOpTextureProjLod:
810             cracked.lod = true;
811             cracked.proj = true;
812             break;
813         case EOpTextureProjLodOffset:
814             cracked.offset = true;
815             cracked.lod = true;
816             cracked.proj = true;
817             break;
818         case EOpTextureGrad:
819         case EOpSparseTextureGrad:
820             cracked.grad = true;
821             break;
822         case EOpTextureGradClamp:
823         case EOpSparseTextureGradClamp:
824             cracked.grad = true;
825             cracked.lodClamp = true;
826             break;
827         case EOpTextureGradOffset:
828         case EOpSparseTextureGradOffset:
829             cracked.grad = true;
830             cracked.offset = true;
831             break;
832         case EOpTextureProjGrad:
833             cracked.grad = true;
834             cracked.proj = true;
835             break;
836         case EOpTextureProjGradOffset:
837             cracked.grad = true;
838             cracked.offset = true;
839             cracked.proj = true;
840             break;
841         case EOpTextureGradOffsetClamp:
842         case EOpSparseTextureGradOffsetClamp:
843             cracked.grad = true;
844             cracked.offset = true;
845             cracked.lodClamp = true;
846             break;
847         case EOpTextureGather:
848         case EOpSparseTextureGather:
849             cracked.gather = true;
850             break;
851         case EOpTextureGatherOffset:
852         case EOpSparseTextureGatherOffset:
853             cracked.gather = true;
854             cracked.offset = true;
855             break;
856         case EOpTextureGatherOffsets:
857         case EOpSparseTextureGatherOffsets:
858             cracked.gather = true;
859             cracked.offsets = true;
860             break;
861         case EOpSubpassLoad:
862         case EOpSubpassLoadMS:
863             cracked.subpass = true;
864             break;
865         default:
866             break;
867         }
868     }
869
870 protected:
871     TIntermOperator(TOperator o) : TIntermTyped(EbtFloat), op(o) {}
872     TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
873     TOperator op;
874 };
875
876 //
877 // Nodes for all the basic binary math operators.
878 //
879 class TIntermBinary : public TIntermOperator {
880 public:
881     TIntermBinary(TOperator o) : TIntermOperator(o) {}
882     virtual void traverse(TIntermTraverser*);
883     virtual void setLeft(TIntermTyped* n) { left = n; }
884     virtual void setRight(TIntermTyped* n) { right = n; }
885     virtual TIntermTyped* getLeft() const { return left; }
886     virtual TIntermTyped* getRight() const { return right; }
887     virtual       TIntermBinary* getAsBinaryNode()       { return this; }
888     virtual const TIntermBinary* getAsBinaryNode() const { return this; }
889     virtual bool promote();
890     virtual void updatePrecision();
891 protected:
892     TIntermTyped* left;
893     TIntermTyped* right;
894 };
895
896 //
897 // Nodes for unary math operators.
898 //
899 class TIntermUnary : public TIntermOperator {
900 public:
901     TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {}
902     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {}
903     virtual void traverse(TIntermTraverser*);
904     virtual void setOperand(TIntermTyped* o) { operand = o; }
905     virtual       TIntermTyped* getOperand() { return operand; }
906     virtual const TIntermTyped* getOperand() const { return operand; }
907     virtual       TIntermUnary* getAsUnaryNode()       { return this; }
908     virtual const TIntermUnary* getAsUnaryNode() const { return this; }
909     virtual bool promote();
910     virtual void updatePrecision();
911 protected:
912     TIntermTyped* operand;
913 };
914
915 typedef TVector<TIntermNode*> TIntermSequence;
916 typedef TVector<int> TQualifierList;
917 //
918 // Nodes that operate on an arbitrary sized set of children.
919 //
920 class TIntermAggregate : public TIntermOperator {
921 public:
922     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), pragmaTable(0) { }
923     TIntermAggregate(TOperator o) : TIntermOperator(o), pragmaTable(0) { }
924     ~TIntermAggregate() { delete pragmaTable; }
925     virtual       TIntermAggregate* getAsAggregate()       { return this; }
926     virtual const TIntermAggregate* getAsAggregate() const { return this; }
927     virtual void setOperator(TOperator o) { op = o; }
928     virtual       TIntermSequence& getSequence()       { return sequence; }
929     virtual const TIntermSequence& getSequence() const { return sequence; }
930     virtual void setName(const TString& n) { name = n; }
931     virtual const TString& getName() const { return name; }
932     virtual void traverse(TIntermTraverser*);
933     virtual void setUserDefined() { userDefined = true; }
934     virtual bool isUserDefined() { return userDefined; }
935     virtual TQualifierList& getQualifierList() { return qualifier; }
936     virtual const TQualifierList& getQualifierList() const { return qualifier; }
937     void setOptimize(bool o) { optimize = o; }
938     void setDebug(bool d) { debug = d; }
939     bool getOptimize() const { return optimize; }
940     bool getDebug() const { return debug; }
941     void addToPragmaTable(const TPragmaTable& pTable);
942     const TPragmaTable& getPragmaTable() const { return *pragmaTable; }
943 protected:
944     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
945     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
946     TIntermSequence sequence;
947     TQualifierList qualifier;
948     TString name;
949     bool userDefined; // used for user defined function names
950     bool optimize;
951     bool debug;
952     TPragmaTable* pragmaTable;
953 };
954
955 //
956 // For if tests.
957 //
958 class TIntermSelection : public TIntermTyped {
959 public:
960     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
961         TIntermTyped(EbtVoid), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
962     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
963         TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
964     virtual void traverse(TIntermTraverser*);
965     virtual TIntermTyped* getCondition() const { return condition; }
966     virtual TIntermNode* getTrueBlock() const { return trueBlock; }
967     virtual TIntermNode* getFalseBlock() const { return falseBlock; }
968     virtual       TIntermSelection* getAsSelectionNode()       { return this; }
969     virtual const TIntermSelection* getAsSelectionNode() const { return this; }
970 protected:
971     TIntermTyped* condition;
972     TIntermNode* trueBlock;
973     TIntermNode* falseBlock;
974 };
975
976 //
977 // For switch statements.  Designed use is that a switch will have sequence of nodes
978 // that are either case/default nodes or a *single* node that represents all the code
979 // in between (if any) consecutive case/defaults.  So, a traversal need only deal with
980 // 0 or 1 nodes per case/default statement.
981 //
982 class TIntermSwitch : public TIntermNode {
983 public:
984     TIntermSwitch(TIntermTyped* cond, TIntermAggregate* b) : condition(cond), body(b) { }
985     virtual void traverse(TIntermTraverser*);
986     virtual TIntermNode* getCondition() const { return condition; }
987     virtual TIntermAggregate* getBody() const { return body; }
988     virtual       TIntermSwitch* getAsSwitchNode()       { return this; }
989     virtual const TIntermSwitch* getAsSwitchNode() const { return this; }
990 protected:
991     TIntermTyped* condition;
992     TIntermAggregate* body;
993 };
994
995 enum TVisit
996 {
997     EvPreVisit,
998     EvInVisit,
999     EvPostVisit
1000 };
1001
1002 //
1003 // For traversing the tree.  User should derive from this, 
1004 // put their traversal specific data in it, and then pass
1005 // it to a Traverse method.
1006 //
1007 // When using this, just fill in the methods for nodes you want visited.
1008 // Return false from a pre-visit to skip visiting that node's subtree.
1009 //
1010 // Explicitly set postVisit to true if you want post visiting, otherwise,
1011 // filled in methods will only be called at pre-visit time (before processing
1012 // the subtree).  Similarly for inVisit for in-order visiting of nodes with
1013 // multiple children.
1014 //
1015 // If you only want post-visits, explicitly turn off preVisit (and inVisit) 
1016 // and turn on postVisit.
1017 //
1018 // In general, for the visit*() methods, return true from interior nodes 
1019 // to have the traversal continue on to children.
1020 //
1021 // If you process children yourself, or don't want them processed, return false.
1022 //
1023 class TIntermTraverser {
1024 public:
1025     POOL_ALLOCATOR_NEW_DELETE(glslang::GetThreadPoolAllocator())
1026     TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
1027             preVisit(preVisit),
1028             inVisit(inVisit),
1029             postVisit(postVisit),
1030             rightToLeft(rightToLeft),
1031             depth(0),
1032             maxDepth(0) { }
1033     virtual ~TIntermTraverser() { }
1034
1035     virtual void visitSymbol(TIntermSymbol*)               { }
1036     virtual void visitConstantUnion(TIntermConstantUnion*) { }
1037     virtual bool visitBinary(TVisit, TIntermBinary*)       { return true; }
1038     virtual bool visitUnary(TVisit, TIntermUnary*)         { return true; }
1039     virtual bool visitSelection(TVisit, TIntermSelection*) { return true; }
1040     virtual bool visitAggregate(TVisit, TIntermAggregate*) { return true; }
1041     virtual bool visitLoop(TVisit, TIntermLoop*)           { return true; }
1042     virtual bool visitBranch(TVisit, TIntermBranch*)       { return true; }
1043     virtual bool visitSwitch(TVisit, TIntermSwitch*)       { return true; }
1044
1045     int getMaxDepth() const { return maxDepth; }
1046
1047     void incrementDepth(TIntermNode *current)
1048     {
1049         depth++;
1050         maxDepth = (std::max)(maxDepth, depth);
1051         path.push_back(current);
1052     }
1053
1054     void decrementDepth()
1055     {
1056         depth--;
1057         path.pop_back();
1058     }
1059
1060     TIntermNode *getParentNode()
1061     {
1062         return path.size() == 0 ? NULL : path.back();
1063     }
1064
1065     const bool preVisit;
1066     const bool inVisit;
1067     const bool postVisit;
1068     const bool rightToLeft;
1069
1070 protected:
1071     TIntermTraverser& operator=(TIntermTraverser&);
1072
1073     int depth;
1074     int maxDepth;
1075
1076     // All the nodes from root to the current node's parent during traversing.
1077     TVector<TIntermNode *> path;
1078 };
1079
1080 // KHR_vulkan_glsl says "Two arrays sized with specialization constants are the same type only if
1081 // sized with the same symbol, involving no operations"
1082 inline bool SameSpecializationConstants(TIntermTyped* node1, TIntermTyped* node2)
1083 {
1084     return node1->getAsSymbolNode() && node2->getAsSymbolNode() &&
1085            node1->getAsSymbolNode()->getId() == node2->getAsSymbolNode()->getId();
1086 }
1087
1088 } // end namespace glslang
1089
1090 #endif // __INTERMEDIATE_H