blob: 5e097186130da2cb85a8f0a932b0eb0d77ecb6c6 [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
Geoff Lang0a73dd82014-11-19 16:18:08 -050016#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_
17#define COMPILER_TRANSLATOR_INTERMNODE_H_
Jamie Madillb1a85f42014-08-19 15:23:24 -040018
19#include "GLSLANG/ShaderLang.h"
20
21#include <algorithm>
22#include <queue>
23
Jamie Madill80d934b2015-02-19 10:16:12 -050024#include "common/angleutils.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040025#include "compiler/translator/Common.h"
26#include "compiler/translator/Types.h"
27#include "compiler/translator/ConstantUnion.h"
Olli Etuaho1033e1d2015-02-12 12:03:13 +020028#include "compiler/translator/Operator.h"
Jamie Madillb1a85f42014-08-19 15:23:24 -040029
30class TIntermTraverser;
31class TIntermAggregate;
32class TIntermBinary;
33class TIntermUnary;
34class TIntermConstantUnion;
35class TIntermSelection;
Olli Etuahoa3a36662015-02-17 13:46:51 +020036class TIntermSwitch;
37class TIntermCase;
Jamie Madillb1a85f42014-08-19 15:23:24 -040038class TIntermTyped;
39class TIntermSymbol;
40class TIntermLoop;
41class TInfoSink;
Olli Etuahoa3a5cc62015-02-13 13:12:22 +020042class TInfoSinkBase;
Jamie Madillb1a85f42014-08-19 15:23:24 -040043class TIntermRaw;
44
45//
46// Base class for the tree nodes
47//
48class TIntermNode
49{
50 public:
51 POOL_ALLOCATOR_NEW_DELETE();
52 TIntermNode()
53 {
54 // TODO: Move this to TSourceLoc constructor
55 // after getting rid of TPublicType.
56 mLine.first_file = mLine.last_file = 0;
57 mLine.first_line = mLine.last_line = 0;
58 }
59 virtual ~TIntermNode() { }
60
61 const TSourceLoc &getLine() const { return mLine; }
62 void setLine(const TSourceLoc &l) { mLine = l; }
63
64 virtual void traverse(TIntermTraverser *) = 0;
65 virtual TIntermTyped *getAsTyped() { return 0; }
66 virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
67 virtual TIntermAggregate *getAsAggregate() { return 0; }
68 virtual TIntermBinary *getAsBinaryNode() { return 0; }
69 virtual TIntermUnary *getAsUnaryNode() { return 0; }
70 virtual TIntermSelection *getAsSelectionNode() { return 0; }
Olli Etuahoa3a36662015-02-17 13:46:51 +020071 virtual TIntermSwitch *getAsSwitchNode() { return 0; }
72 virtual TIntermCase *getAsCaseNode() { return 0; }
Jamie Madillb1a85f42014-08-19 15:23:24 -040073 virtual TIntermSymbol *getAsSymbolNode() { return 0; }
74 virtual TIntermLoop *getAsLoopNode() { return 0; }
75 virtual TIntermRaw *getAsRawNode() { return 0; }
76
77 // Replace a child node. Return true if |original| is a child
78 // node and it is replaced; otherwise, return false.
79 virtual bool replaceChildNode(
80 TIntermNode *original, TIntermNode *replacement) = 0;
81
Jamie Madillb1a85f42014-08-19 15:23:24 -040082 protected:
83 TSourceLoc mLine;
84};
85
86//
87// This is just to help yacc.
88//
89struct TIntermNodePair
90{
91 TIntermNode *node1;
92 TIntermNode *node2;
93};
94
95//
96// Intermediate class for nodes that have a type.
97//
98class TIntermTyped : public TIntermNode
99{
100 public:
101 TIntermTyped(const TType &t) : mType(t) { }
102 virtual TIntermTyped *getAsTyped() { return this; }
103
104 virtual bool hasSideEffects() const = 0;
105
106 void setType(const TType &t) { mType = t; }
Olli Etuahod2a67b92014-10-21 16:42:57 +0300107 void setTypePreservePrecision(const TType &t);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400108 const TType &getType() const { return mType; }
109 TType *getTypePointer() { return &mType; }
110
111 TBasicType getBasicType() const { return mType.getBasicType(); }
112 TQualifier getQualifier() const { return mType.getQualifier(); }
113 TPrecision getPrecision() const { return mType.getPrecision(); }
114 int getCols() const { return mType.getCols(); }
115 int getRows() const { return mType.getRows(); }
116 int getNominalSize() const { return mType.getNominalSize(); }
117 int getSecondarySize() const { return mType.getSecondarySize(); }
118
119 bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
120 bool isMatrix() const { return mType.isMatrix(); }
121 bool isArray() const { return mType.isArray(); }
122 bool isVector() const { return mType.isVector(); }
123 bool isScalar() const { return mType.isScalar(); }
124 bool isScalarInt() const { return mType.isScalarInt(); }
125 const char *getBasicString() const { return mType.getBasicString(); }
126 const char *getQualifierString() const { return mType.getQualifierString(); }
127 TString getCompleteString() const { return mType.getCompleteString(); }
128
129 int getArraySize() const { return mType.getArraySize(); }
130
131 protected:
132 TType mType;
133};
134
135//
136// Handle for, do-while, and while loops.
137//
138enum TLoopType
139{
140 ELoopFor,
141 ELoopWhile,
142 ELoopDoWhile
143};
144
145class TIntermLoop : public TIntermNode
146{
147 public:
148 TIntermLoop(TLoopType type,
149 TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
150 TIntermNode *body)
151 : mType(type),
152 mInit(init),
153 mCond(cond),
154 mExpr(expr),
155 mBody(body),
156 mUnrollFlag(false) { }
157
158 virtual TIntermLoop *getAsLoopNode() { return this; }
159 virtual void traverse(TIntermTraverser *);
160 virtual bool replaceChildNode(
161 TIntermNode *original, TIntermNode *replacement);
162
163 TLoopType getType() const { return mType; }
164 TIntermNode *getInit() { return mInit; }
165 TIntermTyped *getCondition() { return mCond; }
166 TIntermTyped *getExpression() { return mExpr; }
167 TIntermNode *getBody() { return mBody; }
168
169 void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
170 bool getUnrollFlag() const { return mUnrollFlag; }
171
Jamie Madillb1a85f42014-08-19 15:23:24 -0400172 protected:
173 TLoopType mType;
174 TIntermNode *mInit; // for-loop initialization
175 TIntermTyped *mCond; // loop exit condition
176 TIntermTyped *mExpr; // for-loop expression
177 TIntermNode *mBody; // loop body
178
179 bool mUnrollFlag; // Whether the loop should be unrolled or not.
180};
181
182//
183// Handle break, continue, return, and kill.
184//
185class TIntermBranch : public TIntermNode
186{
187 public:
188 TIntermBranch(TOperator op, TIntermTyped *e)
189 : mFlowOp(op),
190 mExpression(e) { }
191
192 virtual void traverse(TIntermTraverser *);
193 virtual bool replaceChildNode(
194 TIntermNode *original, TIntermNode *replacement);
195
196 TOperator getFlowOp() { return mFlowOp; }
197 TIntermTyped* getExpression() { return mExpression; }
198
Jamie Madillb1a85f42014-08-19 15:23:24 -0400199protected:
200 TOperator mFlowOp;
201 TIntermTyped *mExpression; // non-zero except for "return exp;" statements
202};
203
204//
205// Nodes that correspond to symbols or constants in the source code.
206//
207class TIntermSymbol : public TIntermTyped
208{
209 public:
210 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
211 // If sym comes from per process globalpoolallocator, then it causes increased memory usage
212 // per compile it is essential to use "symbol = sym" to assign to symbol
213 TIntermSymbol(int id, const TString &symbol, const TType &type)
214 : TIntermTyped(type),
215 mId(id)
216 {
217 mSymbol = symbol;
218 }
219
220 virtual bool hasSideEffects() const { return false; }
221
222 int getId() const { return mId; }
223 const TString &getSymbol() const { return mSymbol; }
224
225 void setId(int newId) { mId = newId; }
226
227 virtual void traverse(TIntermTraverser *);
228 virtual TIntermSymbol *getAsSymbolNode() { return this; }
229 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
230
Jamie Madillb1a85f42014-08-19 15:23:24 -0400231 protected:
232 int mId;
233 TString mSymbol;
234};
235
236// A Raw node stores raw code, that the translator will insert verbatim
237// into the output stream. Useful for transformation operations that make
238// complex code that might not fit naturally into the GLSL model.
239class TIntermRaw : public TIntermTyped
240{
241 public:
242 TIntermRaw(const TType &type, const TString &rawText)
243 : TIntermTyped(type),
244 mRawText(rawText) { }
245
246 virtual bool hasSideEffects() const { return false; }
247
248 TString getRawText() const { return mRawText; }
249
250 virtual void traverse(TIntermTraverser *);
251
252 virtual TIntermRaw *getAsRawNode() { return this; }
253 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
Jamie Madillb1a85f42014-08-19 15:23:24 -0400254
255 protected:
256 TString mRawText;
257};
258
259class TIntermConstantUnion : public TIntermTyped
260{
261 public:
262 TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type)
263 : TIntermTyped(type),
264 mUnionArrayPointer(unionPointer) { }
265
266 virtual bool hasSideEffects() const { return false; }
267
268 ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
269
270 int getIConst(size_t index) const
271 {
272 return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
273 }
274 unsigned int getUConst(size_t index) const
275 {
276 return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
277 }
278 float getFConst(size_t index) const
279 {
280 return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
281 }
282 bool getBConst(size_t index) const
283 {
284 return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
285 }
286
287 virtual TIntermConstantUnion *getAsConstantUnion() { return this; }
288 virtual void traverse(TIntermTraverser *);
289 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
290
291 TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
292
Jamie Madillb1a85f42014-08-19 15:23:24 -0400293 protected:
294 ConstantUnion *mUnionArrayPointer;
295};
296
297//
298// Intermediate class for node types that hold operators.
299//
300class TIntermOperator : public TIntermTyped
301{
302 public:
303 TOperator getOp() const { return mOp; }
304 void setOp(TOperator op) { mOp = op; }
305
306 bool isAssignment() const;
307 bool isConstructor() const;
308
309 virtual bool hasSideEffects() const { return isAssignment(); }
310
311 protected:
312 TIntermOperator(TOperator op)
313 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
314 mOp(op) {}
315 TIntermOperator(TOperator op, const TType &type)
316 : TIntermTyped(type),
317 mOp(op) {}
318
319 TOperator mOp;
320};
321
322//
323// Nodes for all the basic binary math operators.
324//
325class TIntermBinary : public TIntermOperator
326{
327 public:
328 TIntermBinary(TOperator op)
329 : TIntermOperator(op),
330 mAddIndexClamp(false) {}
331
332 virtual TIntermBinary *getAsBinaryNode() { return this; }
333 virtual void traverse(TIntermTraverser *);
334 virtual bool replaceChildNode(
335 TIntermNode *original, TIntermNode *replacement);
336
337 virtual bool hasSideEffects() const
338 {
339 return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
340 }
341
342 void setLeft(TIntermTyped *node) { mLeft = node; }
343 void setRight(TIntermTyped *node) { mRight = node; }
344 TIntermTyped *getLeft() const { return mLeft; }
345 TIntermTyped *getRight() const { return mRight; }
346 bool promote(TInfoSink &);
347
348 void setAddIndexClamp() { mAddIndexClamp = true; }
349 bool getAddIndexClamp() { return mAddIndexClamp; }
350
Jamie Madillb1a85f42014-08-19 15:23:24 -0400351 protected:
352 TIntermTyped* mLeft;
353 TIntermTyped* mRight;
354
355 // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
356 bool mAddIndexClamp;
357};
358
359//
360// Nodes for unary math operators.
361//
362class TIntermUnary : public TIntermOperator
363{
364 public:
365 TIntermUnary(TOperator op, const TType &type)
366 : TIntermOperator(op, type),
367 mOperand(NULL),
368 mUseEmulatedFunction(false) {}
369 TIntermUnary(TOperator op)
370 : TIntermOperator(op),
371 mOperand(NULL),
372 mUseEmulatedFunction(false) {}
373
374 virtual void traverse(TIntermTraverser *);
375 virtual TIntermUnary *getAsUnaryNode() { return this; }
376 virtual bool replaceChildNode(
377 TIntermNode *original, TIntermNode *replacement);
378
379 virtual bool hasSideEffects() const
380 {
381 return isAssignment() || mOperand->hasSideEffects();
382 }
383
384 void setOperand(TIntermTyped *operand) { mOperand = operand; }
385 TIntermTyped *getOperand() { return mOperand; }
386 bool promote(TInfoSink &);
387
388 void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
389 bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
390
Jamie Madillb1a85f42014-08-19 15:23:24 -0400391 protected:
392 TIntermTyped *mOperand;
393
394 // If set to true, replace the built-in function call with an emulated one
395 // to work around driver bugs.
396 bool mUseEmulatedFunction;
397};
398
399typedef TVector<TIntermNode *> TIntermSequence;
400typedef TVector<int> TQualifierList;
401
402//
403// Nodes that operate on an arbitrary sized set of children.
404//
405class TIntermAggregate : public TIntermOperator
406{
407 public:
408 TIntermAggregate()
409 : TIntermOperator(EOpNull),
410 mUserDefined(false),
411 mUseEmulatedFunction(false) { }
412 TIntermAggregate(TOperator op)
413 : TIntermOperator(op),
414 mUseEmulatedFunction(false) { }
415 ~TIntermAggregate() { }
416
417 virtual TIntermAggregate *getAsAggregate() { return this; }
418 virtual void traverse(TIntermTraverser *);
419 virtual bool replaceChildNode(
420 TIntermNode *original, TIntermNode *replacement);
421
422 // Conservatively assume function calls and other aggregate operators have side-effects
423 virtual bool hasSideEffects() const { return true; }
424
425 TIntermSequence *getSequence() { return &mSequence; }
426
427 void setName(const TString &name) { mName = name; }
428 const TString &getName() const { return mName; }
429
430 void setUserDefined() { mUserDefined = true; }
431 bool isUserDefined() const { return mUserDefined; }
432
433 void setOptimize(bool optimize) { mOptimize = optimize; }
434 bool getOptimize() const { return mOptimize; }
435 void setDebug(bool debug) { mDebug = debug; }
436 bool getDebug() const { return mDebug; }
437
438 void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
439 bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
440
Olli Etuahod2a67b92014-10-21 16:42:57 +0300441 void setPrecisionFromChildren();
442 void setBuiltInFunctionPrecision();
443
Jamie Madillb1a85f42014-08-19 15:23:24 -0400444 protected:
445 TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
446 TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator
447 TIntermSequence mSequence;
448 TString mName;
449 bool mUserDefined; // used for user defined function names
450
451 bool mOptimize;
452 bool mDebug;
453
454 // If set to true, replace the built-in function call with an emulated one
455 // to work around driver bugs.
456 bool mUseEmulatedFunction;
457};
458
459//
Olli Etuahoa3a36662015-02-17 13:46:51 +0200460// For if tests.
Jamie Madillb1a85f42014-08-19 15:23:24 -0400461//
462class TIntermSelection : public TIntermTyped
463{
464 public:
465 TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
466 : TIntermTyped(TType(EbtVoid, EbpUndefined)),
467 mCondition(cond),
468 mTrueBlock(trueB),
469 mFalseBlock(falseB) {}
470 TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB,
471 const TType &type)
472 : TIntermTyped(type),
473 mCondition(cond),
474 mTrueBlock(trueB),
475 mFalseBlock(falseB) {}
476
477 virtual void traverse(TIntermTraverser *);
478 virtual bool replaceChildNode(
479 TIntermNode *original, TIntermNode *replacement);
480
481 // Conservatively assume selections have side-effects
482 virtual bool hasSideEffects() const { return true; }
483
484 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
485 TIntermNode *getCondition() const { return mCondition; }
486 TIntermNode *getTrueBlock() const { return mTrueBlock; }
487 TIntermNode *getFalseBlock() const { return mFalseBlock; }
488 TIntermSelection *getAsSelectionNode() { return this; }
489
Jamie Madillb1a85f42014-08-19 15:23:24 -0400490protected:
491 TIntermTyped *mCondition;
492 TIntermNode *mTrueBlock;
493 TIntermNode *mFalseBlock;
494};
495
Olli Etuahoa3a36662015-02-17 13:46:51 +0200496//
497// Switch statement.
498//
499class TIntermSwitch : public TIntermNode
500{
501 public:
502 TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
503 : TIntermNode(),
504 mInit(init),
505 mStatementList(statementList)
506 {
507 }
508
509 void traverse(TIntermTraverser *it) override;
510 bool replaceChildNode(
511 TIntermNode *original, TIntermNode *replacement) override;
512
513 TIntermSwitch *getAsSwitchNode() override { return this; }
514
515 protected:
516 TIntermTyped *mInit;
517 TIntermAggregate *mStatementList;
518};
519
520//
521// Case label.
522//
523class TIntermCase : public TIntermNode
524{
525 public:
526 TIntermCase(TIntermTyped *condition)
527 : TIntermNode(),
528 mCondition(condition)
529 {
530 }
531
532 void traverse(TIntermTraverser *it) override;
533 bool replaceChildNode(
534 TIntermNode *original, TIntermNode *replacement) override;
535
536 TIntermCase *getAsCaseNode() override { return this; }
537
538 bool hasCondition() const { return mCondition != nullptr; }
539 TIntermTyped *getCondition() const { return mCondition; }
540
541 protected:
542 TIntermTyped *mCondition;
543};
544
Jamie Madillb1a85f42014-08-19 15:23:24 -0400545enum Visit
546{
547 PreVisit,
548 InVisit,
549 PostVisit
550};
551
552//
553// For traversing the tree. User should derive from this,
554// put their traversal specific data in it, and then pass
555// it to a Traverse method.
556//
557// When using this, just fill in the methods for nodes you want visited.
558// Return false from a pre-visit to skip visiting that node's subtree.
559//
560class TIntermTraverser
561{
562 public:
563 POOL_ALLOCATOR_NEW_DELETE();
564 // TODO(zmo): remove default values.
565 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false,
566 bool rightToLeft = false)
567 : preVisit(preVisit),
568 inVisit(inVisit),
569 postVisit(postVisit),
570 rightToLeft(rightToLeft),
571 mDepth(0),
572 mMaxDepth(0) {}
573 virtual ~TIntermTraverser() {}
574
575 virtual void visitSymbol(TIntermSymbol *) {}
576 virtual void visitRaw(TIntermRaw *) {}
577 virtual void visitConstantUnion(TIntermConstantUnion *) {}
578 virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
579 virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
580 virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
Olli Etuahoa3a36662015-02-17 13:46:51 +0200581 virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; }
582 virtual bool visitCase(Visit, TIntermCase *) { return true; }
Jamie Madillb1a85f42014-08-19 15:23:24 -0400583 virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
584 virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
585 virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
586
587 int getMaxDepth() const { return mMaxDepth; }
588
589 void incrementDepth(TIntermNode *current)
590 {
591 mDepth++;
592 mMaxDepth = std::max(mMaxDepth, mDepth);
593 mPath.push_back(current);
594 }
595
596 void decrementDepth()
597 {
598 mDepth--;
599 mPath.pop_back();
600 }
601
602 TIntermNode *getParentNode()
603 {
604 return mPath.size() == 0 ? NULL : mPath.back();
605 }
606
607 // Return the original name if hash function pointer is NULL;
608 // otherwise return the hashed name.
609 static TString hash(const TString& name, ShHashFunction64 hashFunction);
610
611 const bool preVisit;
612 const bool inVisit;
613 const bool postVisit;
614 const bool rightToLeft;
615
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200616 // If traversers need to replace nodes, they can add the replacements in
617 // mReplacements during traversal and the user of the traverser should call
618 // this function after traversal to perform them.
619 void updateTree();
620
Jamie Madillb1a85f42014-08-19 15:23:24 -0400621 protected:
622 int mDepth;
623 int mMaxDepth;
624
625 // All the nodes from root to the current node's parent during traversing.
626 TVector<TIntermNode *> mPath;
Olli Etuaho853dc1a2014-11-06 17:25:48 +0200627
628 struct NodeUpdateEntry
629 {
630 NodeUpdateEntry(TIntermNode *_parent,
631 TIntermNode *_original,
632 TIntermNode *_replacement,
633 bool _originalBecomesChildOfReplacement)
634 : parent(_parent),
635 original(_original),
636 replacement(_replacement),
637 originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {}
638
639 TIntermNode *parent;
640 TIntermNode *original;
641 TIntermNode *replacement;
642 bool originalBecomesChildOfReplacement;
643 };
644
645 // During traversing, save all the changes that need to happen into
646 // mReplacements, then do them by calling updateTree().
647 std::vector<NodeUpdateEntry> mReplacements;
Jamie Madill80d934b2015-02-19 10:16:12 -0500648
649 private:
650 DISALLOW_COPY_AND_ASSIGN(TIntermTraverser);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400651};
652
653//
654// For traversing the tree, and computing max depth.
655// Takes a maximum depth limit to prevent stack overflow.
656//
657class TMaxDepthTraverser : public TIntermTraverser
658{
659 public:
660 POOL_ALLOCATOR_NEW_DELETE();
661 TMaxDepthTraverser(int depthLimit)
662 : TIntermTraverser(true, true, false, false),
663 mDepthLimit(depthLimit) { }
664
665 virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); }
666 virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); }
667 virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); }
668 virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); }
669 virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
670 virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
671
Jamie Madill80d934b2015-02-19 10:16:12 -0500672 protected:
Jamie Madillb1a85f42014-08-19 15:23:24 -0400673 bool depthCheck() const { return mMaxDepth < mDepthLimit; }
674
675 int mDepthLimit;
Jamie Madill80d934b2015-02-19 10:16:12 -0500676
677 private:
678 DISALLOW_COPY_AND_ASSIGN(TMaxDepthTraverser);
Jamie Madillb1a85f42014-08-19 15:23:24 -0400679};
680
Geoff Lang0a73dd82014-11-19 16:18:08 -0500681#endif // COMPILER_TRANSLATOR_INTERMNODE_H_