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