blob: ec440da0109ec2a0f82b9d9c01f97b5984bf6a78 [file] [log] [blame]
Jamie Madillb1a85f42014-08-19 15:23:24 -04001//
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//
31enum 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,
Jamie Madill3b5c2da2014-08-19 15:23:32 -040040 EOpInvariantDeclaration, // Specialized declarations for attributing invariance
Jamie Madillb1a85f42014-08-19 15:23:24 -040041 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
192class TIntermTraverser;
193class TIntermAggregate;
194class TIntermBinary;
195class TIntermUnary;
196class TIntermConstantUnion;
197class TIntermSelection;
198class TIntermTyped;
199class TIntermSymbol;
200class TIntermLoop;
201class TInfoSink;
202class TIntermRaw;
203
204//
205// Base class for the tree nodes
206//
207class 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//
250struct TIntermNodePair
251{
252 TIntermNode *node1;
253 TIntermNode *node2;
254};
255
256//
257// Intermediate class for nodes that have a type.
258//
259class 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//
298enum TLoopType
299{
300 ELoopFor,
301 ELoopWhile,
302 ELoopDoWhile
303};
304
305class 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//
347class 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
363protected:
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//
371class 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.
405class 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
426class 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//
469class 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//
494class 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//
533class 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
572typedef TVector<TIntermNode *> TIntermSequence;
573typedef TVector<int> TQualifierList;
574
575//
576// Nodes that operate on an arbitrary sized set of children.
577//
578class 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//
634class 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
664protected:
665 TIntermTyped *mCondition;
666 TIntermNode *mTrueBlock;
667 TIntermNode *mFalseBlock;
668};
669
670enum 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//
685class 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//
751class 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
766protected:
767 bool depthCheck() const { return mMaxDepth < mDepthLimit; }
768
769 int mDepthLimit;
770};
771
772#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_