blob: 892f2849e04f76d6e362b6dbe93edba4934b998d [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,
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
191class TIntermTraverser;
192class TIntermAggregate;
193class TIntermBinary;
194class TIntermUnary;
195class TIntermConstantUnion;
196class TIntermSelection;
197class TIntermTyped;
198class TIntermSymbol;
199class TIntermLoop;
200class TInfoSink;
201class TIntermRaw;
202
203//
204// Base class for the tree nodes
205//
206class 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//
249struct TIntermNodePair
250{
251 TIntermNode *node1;
252 TIntermNode *node2;
253};
254
255//
256// Intermediate class for nodes that have a type.
257//
258class 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//
297enum TLoopType
298{
299 ELoopFor,
300 ELoopWhile,
301 ELoopDoWhile
302};
303
304class 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//
346class 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
362protected:
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//
370class 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.
404class 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
425class 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//
468class 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//
493class 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//
532class 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
571typedef TVector<TIntermNode *> TIntermSequence;
572typedef TVector<int> TQualifierList;
573
574//
575// Nodes that operate on an arbitrary sized set of children.
576//
577class 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//
633class 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
663protected:
664 TIntermTyped *mCondition;
665 TIntermNode *mTrueBlock;
666 TIntermNode *mFalseBlock;
667};
668
669enum 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//
684class 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//
750class 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
765protected:
766 bool depthCheck() const { return mMaxDepth < mDepthLimit; }
767
768 int mDepthLimit;
769};
770
771#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_