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