• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 //
8 // Definition of the in-memory high-level intermediate representation
9 // of shaders.  This is a tree that parser creates.
10 //
11 // Nodes in the tree are defined as a hierarchy of classes derived from
12 // TIntermNode. Each is a node in a tree.  There is no preset branching factor;
13 // each node can have it's own type of list of children.
14 //
15 
16 #ifndef __INTERMEDIATE_H
17 #define __INTERMEDIATE_H
18 
19 #include "GLSLANG/ShaderLang.h"
20 
21 #include <algorithm>
22 #include <queue>
23 #include "compiler/translator/Common.h"
24 #include "compiler/translator/Types.h"
25 #include "compiler/translator/ConstantUnion.h"
26 
27 //
28 // Operators used by the high-level (parse tree) representation.
29 //
30 enum TOperator {
31     EOpNull,            // if in a node, should only mean a node is still being built
32     EOpSequence,        // denotes a list of statements, or parameters, etc.
33     EOpFunctionCall,
34     EOpFunction,        // For function definition
35     EOpParameters,      // an aggregate listing the parameters to a function
36 
37     EOpDeclaration,
38     EOpPrototype,
39 
40     //
41     // Unary operators
42     //
43 
44     EOpNegative,
45     EOpLogicalNot,
46     EOpVectorLogicalNot,
47 
48     EOpPostIncrement,
49     EOpPostDecrement,
50     EOpPreIncrement,
51     EOpPreDecrement,
52 
53     EOpConvIntToBool,
54     EOpConvUIntToBool,
55     EOpConvFloatToBool,
56     EOpConvBoolToFloat,
57     EOpConvIntToFloat,
58     EOpConvUIntToFloat,
59     EOpConvFloatToInt,
60     EOpConvBoolToInt,
61     EOpConvUIntToInt,
62     EOpConvIntToUInt,
63     EOpConvFloatToUInt,
64     EOpConvBoolToUInt,
65 
66     //
67     // binary operations
68     //
69 
70     EOpAdd,
71     EOpSub,
72     EOpMul,
73     EOpDiv,
74     EOpEqual,
75     EOpNotEqual,
76     EOpVectorEqual,
77     EOpVectorNotEqual,
78     EOpLessThan,
79     EOpGreaterThan,
80     EOpLessThanEqual,
81     EOpGreaterThanEqual,
82     EOpComma,
83 
84     EOpVectorTimesScalar,
85     EOpVectorTimesMatrix,
86     EOpMatrixTimesVector,
87     EOpMatrixTimesScalar,
88 
89     EOpLogicalOr,
90     EOpLogicalXor,
91     EOpLogicalAnd,
92 
93     EOpIndexDirect,
94     EOpIndexIndirect,
95     EOpIndexDirectStruct,
96     EOpIndexDirectInterfaceBlock,
97 
98     EOpVectorSwizzle,
99 
100     //
101     // Built-in functions potentially mapped to operators
102     //
103 
104     EOpRadians,
105     EOpDegrees,
106     EOpSin,
107     EOpCos,
108     EOpTan,
109     EOpAsin,
110     EOpAcos,
111     EOpAtan,
112 
113     EOpPow,
114     EOpExp,
115     EOpLog,
116     EOpExp2,
117     EOpLog2,
118     EOpSqrt,
119     EOpInverseSqrt,
120 
121     EOpAbs,
122     EOpSign,
123     EOpFloor,
124     EOpCeil,
125     EOpFract,
126     EOpMod,
127     EOpMin,
128     EOpMax,
129     EOpClamp,
130     EOpMix,
131     EOpStep,
132     EOpSmoothStep,
133 
134     EOpLength,
135     EOpDistance,
136     EOpDot,
137     EOpCross,
138     EOpNormalize,
139     EOpFaceForward,
140     EOpReflect,
141     EOpRefract,
142 
143     EOpDFdx,            // Fragment only, OES_standard_derivatives extension
144     EOpDFdy,            // Fragment only, OES_standard_derivatives extension
145     EOpFwidth,          // Fragment only, OES_standard_derivatives extension
146 
147     EOpMatrixTimesMatrix,
148 
149     EOpAny,
150     EOpAll,
151 
152     //
153     // Branch
154     //
155 
156     EOpKill,            // Fragment only
157     EOpReturn,
158     EOpBreak,
159     EOpContinue,
160 
161     //
162     // Constructors
163     //
164 
165     EOpConstructInt,
166     EOpConstructUInt,
167     EOpConstructBool,
168     EOpConstructFloat,
169     EOpConstructVec2,
170     EOpConstructVec3,
171     EOpConstructVec4,
172     EOpConstructBVec2,
173     EOpConstructBVec3,
174     EOpConstructBVec4,
175     EOpConstructIVec2,
176     EOpConstructIVec3,
177     EOpConstructIVec4,
178     EOpConstructUVec2,
179     EOpConstructUVec3,
180     EOpConstructUVec4,
181     EOpConstructMat2,
182     EOpConstructMat3,
183     EOpConstructMat4,
184     EOpConstructStruct,
185 
186     //
187     // moves
188     //
189 
190     EOpAssign,
191     EOpInitialize,
192     EOpAddAssign,
193     EOpSubAssign,
194     EOpMulAssign,
195     EOpVectorTimesMatrixAssign,
196     EOpVectorTimesScalarAssign,
197     EOpMatrixTimesScalarAssign,
198     EOpMatrixTimesMatrixAssign,
199     EOpDivAssign
200 };
201 
202 extern const char* getOperatorString(TOperator op);
203 
204 class TIntermTraverser;
205 class TIntermAggregate;
206 class TIntermBinary;
207 class TIntermUnary;
208 class TIntermConstantUnion;
209 class TIntermSelection;
210 class TIntermTyped;
211 class TIntermSymbol;
212 class TIntermLoop;
213 class TInfoSink;
214 class TIntermRaw;
215 
216 //
217 // Base class for the tree nodes
218 //
219 class TIntermNode {
220 public:
221     POOL_ALLOCATOR_NEW_DELETE();
TIntermNode()222     TIntermNode() {
223         // TODO: Move this to TSourceLoc constructor
224         // after getting rid of TPublicType.
225         line.first_file = line.last_file = 0;
226         line.first_line = line.last_line = 0;
227     }
~TIntermNode()228     virtual ~TIntermNode() { }
229 
getLine()230     const TSourceLoc& getLine() const { return line; }
setLine(const TSourceLoc & l)231     void setLine(const TSourceLoc& l) { line = l; }
232 
233     virtual void traverse(TIntermTraverser*) = 0;
getAsTyped()234     virtual TIntermTyped* getAsTyped() { return 0; }
getAsConstantUnion()235     virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
getAsAggregate()236     virtual TIntermAggregate* getAsAggregate() { return 0; }
getAsBinaryNode()237     virtual TIntermBinary* getAsBinaryNode() { return 0; }
getAsUnaryNode()238     virtual TIntermUnary* getAsUnaryNode() { return 0; }
getAsSelectionNode()239     virtual TIntermSelection* getAsSelectionNode() { return 0; }
getAsSymbolNode()240     virtual TIntermSymbol* getAsSymbolNode() { return 0; }
getAsLoopNode()241     virtual TIntermLoop* getAsLoopNode() { return 0; }
getAsRawNode()242     virtual TIntermRaw* getAsRawNode() { return 0; }
243 
244     // Replace a child node. Return true if |original| is a child
245     // node and it is replaced; otherwise, return false.
246     virtual bool replaceChildNode(
247         TIntermNode *original, TIntermNode *replacement) = 0;
248 
249     // For traversing a tree in no particular order, but using
250     // heap memory.
251     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const = 0;
252 
253 protected:
254     TSourceLoc line;
255 };
256 
257 //
258 // This is just to help yacc.
259 //
260 struct TIntermNodePair {
261     TIntermNode* node1;
262     TIntermNode* node2;
263 };
264 
265 //
266 // Intermediate class for nodes that have a type.
267 //
268 class TIntermTyped : public TIntermNode {
269 public:
TIntermTyped(const TType & t)270     TIntermTyped(const TType& t) : type(t)  { }
getAsTyped()271     virtual TIntermTyped* getAsTyped() { return this; }
272 
273     virtual bool hasSideEffects() const = 0;
274 
setType(const TType & t)275     void setType(const TType& t) { type = t; }
getType()276     const TType& getType() const { return type; }
getTypePointer()277     TType* getTypePointer() { return &type; }
278 
getBasicType()279     TBasicType getBasicType() const { return type.getBasicType(); }
getQualifier()280     TQualifier getQualifier() const { return type.getQualifier(); }
getPrecision()281     TPrecision getPrecision() const { return type.getPrecision(); }
getCols()282     int getCols() const { return type.getCols(); }
getRows()283     int getRows() const { return type.getRows(); }
getNominalSize()284     int getNominalSize() const { return type.getNominalSize(); }
getSecondarySize()285     int getSecondarySize() const { return type.getSecondarySize(); }
286 
isInterfaceBlock()287     bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
isMatrix()288     bool isMatrix() const { return type.isMatrix(); }
isArray()289     bool isArray()  const { return type.isArray(); }
isVector()290     bool isVector() const { return type.isVector(); }
isScalar()291     bool isScalar() const { return type.isScalar(); }
isScalarInt()292     bool isScalarInt() const { return type.isScalarInt(); }
getBasicString()293     const char* getBasicString() const { return type.getBasicString(); }
getQualifierString()294     const char* getQualifierString() const { return type.getQualifierString(); }
getCompleteString()295     TString getCompleteString() const { return type.getCompleteString(); }
296 
getArraySize()297     int getArraySize() const { return type.getArraySize(); }
298 
299 protected:
300     TType type;
301 };
302 
303 //
304 // Handle for, do-while, and while loops.
305 //
306 enum TLoopType {
307     ELoopFor,
308     ELoopWhile,
309     ELoopDoWhile
310 };
311 
312 class TIntermLoop : public TIntermNode {
313 public:
TIntermLoop(TLoopType aType,TIntermNode * aInit,TIntermTyped * aCond,TIntermTyped * aExpr,TIntermNode * aBody)314     TIntermLoop(TLoopType aType,
315                 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
316                 TIntermNode* aBody) :
317             type(aType),
318             init(aInit),
319             cond(aCond),
320             expr(aExpr),
321             body(aBody),
322             unrollFlag(false) { }
323 
getAsLoopNode()324     virtual TIntermLoop* getAsLoopNode() { return this; }
325     virtual void traverse(TIntermTraverser*);
326     virtual bool replaceChildNode(
327         TIntermNode *original, TIntermNode *replacement);
328 
getType()329     TLoopType getType() const { return type; }
getInit()330     TIntermNode* getInit() { return init; }
getCondition()331     TIntermTyped* getCondition() { return cond; }
getExpression()332     TIntermTyped* getExpression() { return expr; }
getBody()333     TIntermNode* getBody() { return body; }
334 
setUnrollFlag(bool flag)335     void setUnrollFlag(bool flag) { unrollFlag = flag; }
getUnrollFlag()336     bool getUnrollFlag() { return unrollFlag; }
337 
338     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
339 
340 protected:
341     TLoopType type;
342     TIntermNode* init;  // for-loop initialization
343     TIntermTyped* cond; // loop exit condition
344     TIntermTyped* expr; // for-loop expression
345     TIntermNode* body;  // loop body
346 
347     bool unrollFlag; // Whether the loop should be unrolled or not.
348 };
349 
350 //
351 // Handle break, continue, return, and kill.
352 //
353 class TIntermBranch : public TIntermNode {
354 public:
TIntermBranch(TOperator op,TIntermTyped * e)355     TIntermBranch(TOperator op, TIntermTyped* e) :
356             flowOp(op),
357             expression(e) { }
358 
359     virtual void traverse(TIntermTraverser*);
360     virtual bool replaceChildNode(
361         TIntermNode *original, TIntermNode *replacement);
362 
getFlowOp()363     TOperator getFlowOp() { return flowOp; }
getExpression()364     TIntermTyped* getExpression() { return expression; }
365 
366     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
367 
368 protected:
369     TOperator flowOp;
370     TIntermTyped* expression;  // non-zero except for "return exp;" statements
371 };
372 
373 //
374 // Nodes that correspond to symbols or constants in the source code.
375 //
376 class TIntermSymbol : public TIntermTyped {
377 public:
378     // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
379     // per process globalpoolallocator, then it causes increased memory usage per compile
380     // it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(int i,const TString & sym,const TType & t)381     TIntermSymbol(int i, const TString& sym, const TType& t) :
382         TIntermTyped(t), id(i)  { symbol = sym; }
383 
hasSideEffects()384     virtual bool hasSideEffects() const { return false; }
385 
getId()386     int getId() const { return id; }
getSymbol()387     const TString& getSymbol() const { return symbol; }
388 
setId(int newId)389     void setId(int newId) { id = newId; }
390 
391     virtual void traverse(TIntermTraverser*);
getAsSymbolNode()392     virtual TIntermSymbol* getAsSymbolNode() { return this; }
replaceChildNode(TIntermNode *,TIntermNode *)393     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
394 
enqueueChildren(std::queue<TIntermNode * > * nodeQueue)395     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
396 
397 protected:
398     int id;
399     TString symbol;
400 };
401 
402 // A Raw node stores raw code, that the translator will insert verbatim
403 // into the output stream. Useful for transformation operations that make
404 // complex code that might not fit naturally into the GLSL model.
405 class TIntermRaw : public TIntermTyped {
406 public:
TIntermRaw(const TType & t,const TString & rawTextIn)407     TIntermRaw(const TType &t, const TString &rawTextIn)
408         : TIntermTyped(t), rawText(rawTextIn)
409     {}
410 
hasSideEffects()411     virtual bool hasSideEffects() const { return false; }
412 
getRawText()413     TString getRawText() const { return rawText; }
414 
415     virtual void traverse(TIntermTraverser*);
416 
getAsRawNode()417     virtual TIntermRaw* getAsRawNode() { return this; }
replaceChildNode(TIntermNode *,TIntermNode *)418     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
enqueueChildren(std::queue<TIntermNode * > * nodeQueue)419     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
420 
421 protected:
422     TString rawText;
423 };
424 
425 class TIntermConstantUnion : public TIntermTyped {
426 public:
TIntermConstantUnion(ConstantUnion * unionPointer,const TType & t)427     TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
428 
hasSideEffects()429     virtual bool hasSideEffects() const { return false; }
430 
getUnionArrayPointer()431     ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
432 
getIConst(size_t index)433     int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
getUConst(size_t index)434     unsigned int getUConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
getFConst(size_t index)435     float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
getBConst(size_t index)436     bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
437 
getAsConstantUnion()438     virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
439     virtual void traverse(TIntermTraverser*);
replaceChildNode(TIntermNode *,TIntermNode *)440     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
441 
442     TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
443 
enqueueChildren(std::queue<TIntermNode * > * nodeQueue)444     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
445 
446 protected:
447     ConstantUnion *unionArrayPointer;
448 };
449 
450 //
451 // Intermediate class for node types that hold operators.
452 //
453 class TIntermOperator : public TIntermTyped {
454 public:
getOp()455     TOperator getOp() const { return op; }
setOp(TOperator o)456     void setOp(TOperator o) { op = o; }
457 
458     bool isAssignment() const;
459     bool isConstructor() const;
460 
hasSideEffects()461     virtual bool hasSideEffects() const { return isAssignment(); }
462 
463 protected:
TIntermOperator(TOperator o)464     TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
TIntermOperator(TOperator o,const TType & t)465     TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {}
466     TOperator op;
467 };
468 
469 //
470 // Nodes for all the basic binary math operators.
471 //
472 class TIntermBinary : public TIntermOperator {
473 public:
TIntermBinary(TOperator o)474     TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
475 
getAsBinaryNode()476     virtual TIntermBinary* getAsBinaryNode() { return this; }
477     virtual void traverse(TIntermTraverser*);
478     virtual bool replaceChildNode(
479         TIntermNode *original, TIntermNode *replacement);
480 
hasSideEffects()481     virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
482 
setLeft(TIntermTyped * n)483     void setLeft(TIntermTyped* n) { left = n; }
setRight(TIntermTyped * n)484     void setRight(TIntermTyped* n) { right = n; }
getLeft()485     TIntermTyped* getLeft() const { return left; }
getRight()486     TIntermTyped* getRight() const { return right; }
487     bool promote(TInfoSink&);
488 
setAddIndexClamp()489     void setAddIndexClamp() { addIndexClamp = true; }
getAddIndexClamp()490     bool getAddIndexClamp() { return addIndexClamp; }
491 
492     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
493 
494 protected:
495     TIntermTyped* left;
496     TIntermTyped* right;
497 
498     // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
499     bool addIndexClamp;
500 };
501 
502 //
503 // Nodes for unary math operators.
504 //
505 class TIntermUnary : public TIntermOperator {
506 public:
TIntermUnary(TOperator o,const TType & t)507     TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
TIntermUnary(TOperator o)508     TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
509 
510     virtual void traverse(TIntermTraverser*);
getAsUnaryNode()511     virtual TIntermUnary* getAsUnaryNode() { return this; }
512     virtual bool replaceChildNode(
513         TIntermNode *original, TIntermNode *replacement);
514 
hasSideEffects()515     virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
516 
setOperand(TIntermTyped * o)517     void setOperand(TIntermTyped* o) { operand = o; }
getOperand()518     TIntermTyped* getOperand() { return operand; }
519     bool promote(TInfoSink&);
520 
setUseEmulatedFunction()521     void setUseEmulatedFunction() { useEmulatedFunction = true; }
getUseEmulatedFunction()522     bool getUseEmulatedFunction() { return useEmulatedFunction; }
523 
524     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
525 
526 protected:
527     TIntermTyped* operand;
528 
529     // If set to true, replace the built-in function call with an emulated one
530     // to work around driver bugs.
531     bool useEmulatedFunction;
532 };
533 
534 typedef TVector<TIntermNode*> TIntermSequence;
535 typedef TVector<int> TQualifierList;
536 
537 //
538 // Nodes that operate on an arbitrary sized set of children.
539 //
540 class TIntermAggregate : public TIntermOperator {
541 public:
TIntermAggregate()542     TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
TIntermAggregate(TOperator o)543     TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
~TIntermAggregate()544     ~TIntermAggregate() { }
545 
getAsAggregate()546     virtual TIntermAggregate* getAsAggregate() { return this; }
547     virtual void traverse(TIntermTraverser*);
548     virtual bool replaceChildNode(
549         TIntermNode *original, TIntermNode *replacement);
550 
551     // Conservatively assume function calls and other aggregate operators have side-effects
hasSideEffects()552     virtual bool hasSideEffects() const { return true; }
553 
getSequence()554     TIntermSequence& getSequence() { return sequence; }
555 
setName(const TString & n)556     void setName(const TString& n) { name = n; }
getName()557     const TString& getName() const { return name; }
558 
setUserDefined()559     void setUserDefined() { userDefined = true; }
isUserDefined()560     bool isUserDefined() const { return userDefined; }
561 
setOptimize(bool o)562     void setOptimize(bool o) { optimize = o; }
getOptimize()563     bool getOptimize() { return optimize; }
setDebug(bool d)564     void setDebug(bool d) { debug = d; }
getDebug()565     bool getDebug() { return debug; }
566 
setUseEmulatedFunction()567     void setUseEmulatedFunction() { useEmulatedFunction = true; }
getUseEmulatedFunction()568     bool getUseEmulatedFunction() { return useEmulatedFunction; }
569 
570     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
571 
572 protected:
573     TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
574     TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
575     TIntermSequence sequence;
576     TString name;
577     bool userDefined; // used for user defined function names
578 
579     bool optimize;
580     bool debug;
581 
582     // If set to true, replace the built-in function call with an emulated one
583     // to work around driver bugs.
584     bool useEmulatedFunction;
585 };
586 
587 //
588 // For if tests.  Simplified since there is no switch statement.
589 //
590 class TIntermSelection : public TIntermTyped {
591 public:
TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB)592     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
593             TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB,const TType & type)594     TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
595             TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
596 
597     virtual void traverse(TIntermTraverser*);
598     virtual bool replaceChildNode(
599         TIntermNode *original, TIntermNode *replacement);
600 
601     // Conservatively assume selections have side-effects
hasSideEffects()602     virtual bool hasSideEffects() const { return true; }
603 
usesTernaryOperator()604     bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
getCondition()605     TIntermNode* getCondition() const { return condition; }
getTrueBlock()606     TIntermNode* getTrueBlock() const { return trueBlock; }
getFalseBlock()607     TIntermNode* getFalseBlock() const { return falseBlock; }
getAsSelectionNode()608     TIntermSelection* getAsSelectionNode() { return this; }
609 
610     virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
611 
612 protected:
613     TIntermTyped* condition;
614     TIntermNode* trueBlock;
615     TIntermNode* falseBlock;
616 };
617 
618 enum Visit
619 {
620     PreVisit,
621     InVisit,
622     PostVisit
623 };
624 
625 //
626 // For traversing the tree.  User should derive from this,
627 // put their traversal specific data in it, and then pass
628 // it to a Traverse method.
629 //
630 // When using this, just fill in the methods for nodes you want visited.
631 // Return false from a pre-visit to skip visiting that node's subtree.
632 //
633 class TIntermTraverser
634 {
635 public:
636     POOL_ALLOCATOR_NEW_DELETE();
637     TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
preVisit(preVisit)638             preVisit(preVisit),
639             inVisit(inVisit),
640             postVisit(postVisit),
641             rightToLeft(rightToLeft),
642             depth(0),
643             maxDepth(0) {}
~TIntermTraverser()644     virtual ~TIntermTraverser() {}
645 
visitSymbol(TIntermSymbol *)646     virtual void visitSymbol(TIntermSymbol*) {}
visitRaw(TIntermRaw *)647     virtual void visitRaw(TIntermRaw*) {}
visitConstantUnion(TIntermConstantUnion *)648     virtual void visitConstantUnion(TIntermConstantUnion*) {}
visitBinary(Visit visit,TIntermBinary *)649     virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
visitUnary(Visit visit,TIntermUnary *)650     virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
visitSelection(Visit visit,TIntermSelection *)651     virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
visitAggregate(Visit visit,TIntermAggregate *)652     virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
visitLoop(Visit visit,TIntermLoop *)653     virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
visitBranch(Visit visit,TIntermBranch *)654     virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
655 
getMaxDepth()656     int getMaxDepth() const {return maxDepth;}
657 
incrementDepth(TIntermNode * current)658     void incrementDepth(TIntermNode *current)
659     {
660         depth++;
661         maxDepth = std::max(maxDepth, depth);
662         path.push_back(current);
663     }
664 
decrementDepth()665     void decrementDepth()
666     {
667         depth--;
668         path.pop_back();
669     }
670 
getParentNode()671     TIntermNode *getParentNode()
672     {
673         return path.size() == 0 ? NULL : path.back();
674     }
675 
676     // Return the original name if hash function pointer is NULL;
677     // otherwise return the hashed name.
678     static TString hash(const TString& name, ShHashFunction64 hashFunction);
679 
680     const bool preVisit;
681     const bool inVisit;
682     const bool postVisit;
683     const bool rightToLeft;
684 
685 protected:
686     int depth;
687     int maxDepth;
688 
689     // All the nodes from root to the current node's parent during traversing.
690     TVector<TIntermNode *> path;
691 };
692 
693 //
694 // For traversing the tree, and computing max depth.
695 // Takes a maximum depth limit to prevent stack overflow.
696 //
697 class TMaxDepthTraverser : public TIntermTraverser
698 {
699 public:
700     POOL_ALLOCATOR_NEW_DELETE();
TMaxDepthTraverser(int depthLimit)701     TMaxDepthTraverser(int depthLimit)
702       : TIntermTraverser(true, true, false, false),
703         depthLimit(depthLimit)
704     {}
705 
visitBinary(Visit visit,TIntermBinary *)706     virtual bool visitBinary(Visit visit, TIntermBinary*) { return depthCheck(); }
visitUnary(Visit visit,TIntermUnary *)707     virtual bool visitUnary(Visit visit, TIntermUnary*) { return depthCheck(); }
visitSelection(Visit visit,TIntermSelection *)708     virtual bool visitSelection(Visit visit, TIntermSelection*) { return depthCheck(); }
visitAggregate(Visit visit,TIntermAggregate *)709     virtual bool visitAggregate(Visit visit, TIntermAggregate*) { return depthCheck(); }
visitLoop(Visit visit,TIntermLoop *)710     virtual bool visitLoop(Visit visit, TIntermLoop*) { return depthCheck(); }
visitBranch(Visit visit,TIntermBranch *)711     virtual bool visitBranch(Visit visit, TIntermBranch*) { return depthCheck(); }
712 
713 protected:
714     int depthLimit;
715 
depthCheck()716     bool depthCheck() const { return maxDepth < depthLimit; }
717 };
718 
719 #endif // __INTERMEDIATE_H
720