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