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