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