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