Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / compiler / translator / IntermNode.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     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();
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     }
218     virtual ~TIntermNode() { }
219
220     const TSourceLoc &getLine() const { return mLine; }
221     void setLine(const TSourceLoc &l) { mLine = l; }
222
223     virtual void traverse(TIntermTraverser *) = 0;
224     virtual TIntermTyped *getAsTyped() { return 0; }
225     virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
226     virtual TIntermAggregate *getAsAggregate() { return 0; }
227     virtual TIntermBinary *getAsBinaryNode() { return 0; }
228     virtual TIntermUnary *getAsUnaryNode() { return 0; }
229     virtual TIntermSelection *getAsSelectionNode() { return 0; }
230     virtual TIntermSymbol *getAsSymbolNode() { return 0; }
231     virtual TIntermLoop *getAsLoopNode() { return 0; }
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:
262     TIntermTyped(const TType &t) : mType(t)  { }
263     virtual TIntermTyped *getAsTyped() { return this; }
264
265     virtual bool hasSideEffects() const = 0;
266
267     void setType(const TType &t) { mType = t; }
268     const TType &getType() const { return mType; }
269     TType *getTypePointer() { return &mType; }
270
271     TBasicType getBasicType() const { return mType.getBasicType(); }
272     TQualifier getQualifier() const { return mType.getQualifier(); }
273     TPrecision getPrecision() const { return mType.getPrecision(); }
274     int getCols() const { return mType.getCols(); }
275     int getRows() const { return mType.getRows(); }
276     int getNominalSize() const { return mType.getNominalSize(); }
277     int getSecondarySize() const { return mType.getSecondarySize(); }
278
279     bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
280     bool isMatrix() const { return mType.isMatrix(); }
281     bool isArray()  const { return mType.isArray(); }
282     bool isVector() const { return mType.isVector(); }
283     bool isScalar() const { return mType.isScalar(); }
284     bool isScalarInt() const { return mType.isScalarInt(); }
285     const char *getBasicString() const { return mType.getBasicString(); }
286     const char *getQualifierString() const { return mType.getQualifierString(); }
287     TString getCompleteString() const { return mType.getCompleteString(); }
288
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:
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
318     virtual TIntermLoop *getAsLoopNode() { return this; }
319     virtual void traverse(TIntermTraverser *);
320     virtual bool replaceChildNode(
321         TIntermNode *original, TIntermNode *replacement);
322
323     TLoopType getType() const { return mType; }
324     TIntermNode *getInit() { return mInit; }
325     TIntermTyped *getCondition() { return mCond; }
326     TIntermTyped *getExpression() { return mExpr; }
327     TIntermNode *getBody() { return mBody; }
328
329     void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
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:
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
358     TOperator getFlowOp() { return mFlowOp; }
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
377     TIntermSymbol(int id, const TString &symbol, const TType &type)
378         : TIntermTyped(type),
379           mId(id)
380     {
381         mSymbol = symbol;
382     }
383
384     virtual bool hasSideEffects() const { return false; }
385
386     int getId() const { return mId; }
387     const TString &getSymbol() const { return mSymbol; }
388
389     void setId(int newId) { mId = newId; }
390
391     virtual void traverse(TIntermTraverser *);
392     virtual TIntermSymbol *getAsSymbolNode() { return this; }
393     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
394
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:
408     TIntermRaw(const TType &type, const TString &rawText)
409         : TIntermTyped(type),
410           mRawText(rawText) { }
411
412     virtual bool hasSideEffects() const { return false; }
413
414     TString getRawText() const { return mRawText; }
415
416     virtual void traverse(TIntermTraverser *);
417
418     virtual TIntermRaw *getAsRawNode() { return this; }
419     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
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:
429     TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type)
430         : TIntermTyped(type),
431           mUnionArrayPointer(unionPointer) { }
432
433     virtual bool hasSideEffects() const { return false; }
434
435     ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
436
437     int getIConst(size_t index) const
438     {
439         return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
440     }
441     unsigned int getUConst(size_t index) const
442     {
443         return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
444     }
445     float getFConst(size_t index) const
446     {
447         return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
448     }
449     bool getBConst(size_t index) const
450     {
451         return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
452     }
453
454     virtual TIntermConstantUnion *getAsConstantUnion()  { return this; }
455     virtual void traverse(TIntermTraverser *);
456     virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
457
458     TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
459
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:
472     TOperator getOp() const { return mOp; }
473     void setOp(TOperator op) { mOp = op; }
474
475     bool isAssignment() const;
476     bool isConstructor() const;
477
478     virtual bool hasSideEffects() const { return isAssignment(); }
479
480   protected:
481     TIntermOperator(TOperator op)
482         : TIntermTyped(TType(EbtFloat, EbpUndefined)),
483           mOp(op) {}
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:
497     TIntermBinary(TOperator op)
498         : TIntermOperator(op),
499           mAddIndexClamp(false) {}
500
501     virtual TIntermBinary *getAsBinaryNode() { return this; }
502     virtual void traverse(TIntermTraverser *);
503     virtual bool replaceChildNode(
504         TIntermNode *original, TIntermNode *replacement);
505
506     virtual bool hasSideEffects() const
507     {
508         return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
509     }
510
511     void setLeft(TIntermTyped *node) { mLeft = node; }
512     void setRight(TIntermTyped *node) { mRight = node; }
513     TIntermTyped *getLeft() const { return mLeft; }
514     TIntermTyped *getRight() const { return mRight; }
515     bool promote(TInfoSink &);
516
517     void setAddIndexClamp() { mAddIndexClamp = true; }
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:
536     TIntermUnary(TOperator op, const TType &type)
537         : TIntermOperator(op, type),
538           mOperand(NULL),
539           mUseEmulatedFunction(false) {}
540     TIntermUnary(TOperator op)
541         : TIntermOperator(op),
542           mOperand(NULL),
543           mUseEmulatedFunction(false) {}
544
545     virtual void traverse(TIntermTraverser *);
546     virtual TIntermUnary *getAsUnaryNode() { return this; }
547     virtual bool replaceChildNode(
548         TIntermNode *original, TIntermNode *replacement);
549
550     virtual bool hasSideEffects() const
551     {
552         return isAssignment() || mOperand->hasSideEffects();
553     }
554
555     void setOperand(TIntermTyped *operand) { mOperand = operand; }
556     TIntermTyped *getOperand() { return mOperand; }
557     bool promote(TInfoSink &);
558
559     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
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:
581     TIntermAggregate()
582         : TIntermOperator(EOpNull),
583           mUserDefined(false),
584           mUseEmulatedFunction(false) { }
585     TIntermAggregate(TOperator op)
586         : TIntermOperator(op),
587           mUseEmulatedFunction(false) { }
588     ~TIntermAggregate() { }
589
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
596     virtual bool hasSideEffects() const { return true; }
597
598     TIntermSequence *getSequence() { return &mSequence; }
599
600     void setName(const TString &name) { mName = name; }
601     const TString &getName() const { return mName; }
602
603     void setUserDefined() { mUserDefined = true; }
604     bool isUserDefined() const { return mUserDefined; }
605
606     void setOptimize(bool optimize) { mOptimize = optimize; }
607     bool getOptimize() const { return mOptimize; }
608     void setDebug(bool debug) { mDebug = debug; }
609     bool getDebug() const { return mDebug; }
610
611     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
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:
637     TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
638         : TIntermTyped(TType(EbtVoid, EbpUndefined)),
639           mCondition(cond),
640           mTrueBlock(trueB),
641           mFalseBlock(falseB) {}
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
654     virtual bool hasSideEffects() const { return true; }
655
656     bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
657     TIntermNode *getCondition() const { return mCondition; }
658     TIntermNode *getTrueBlock() const { return mTrueBlock; }
659     TIntermNode *getFalseBlock() const { return mFalseBlock; }
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)
692         : preVisit(preVisit),
693           inVisit(inVisit),
694           postVisit(postVisit),
695           rightToLeft(rightToLeft),
696           mDepth(0),
697           mMaxDepth(0) {}
698     virtual ~TIntermTraverser() {}
699
700     virtual void visitSymbol(TIntermSymbol *) {}
701     virtual void visitRaw(TIntermRaw *) {}
702     virtual void visitConstantUnion(TIntermConstantUnion *) {}
703     virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
704     virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
705     virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
706     virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
707     virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
708     virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
709
710     int getMaxDepth() const { return mMaxDepth; }
711
712     void incrementDepth(TIntermNode *current)
713     {
714         mDepth++;
715         mMaxDepth = std::max(mMaxDepth, mDepth);
716         mPath.push_back(current);
717     }
718
719     void decrementDepth()
720     {
721         mDepth--;
722         mPath.pop_back();
723     }
724
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();
755     TMaxDepthTraverser(int depthLimit)
756         : TIntermTraverser(true, true, false, false),
757           mDepthLimit(depthLimit) { }
758
759     virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); }
760     virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); }
761     virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); }
762     virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); }
763     virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
764     virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
765
766 protected:
767     bool depthCheck() const { return mMaxDepth < mDepthLimit; }
768
769     int mDepthLimit;
770 };
771
772 #endif  // COMPILER_TRANSLATOR_INTERMEDIATE_H_