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