LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - IntermNode.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 319 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 267 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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_INTERMNODE_H_
      17             : #define COMPILER_TRANSLATOR_INTERMNODE_H_
      18             : 
      19             : #include "GLSLANG/ShaderLang.h"
      20             : 
      21             : #include <algorithm>
      22             : #include <queue>
      23             : 
      24             : #include "common/angleutils.h"
      25             : #include "compiler/translator/Common.h"
      26             : #include "compiler/translator/ConstantUnion.h"
      27             : #include "compiler/translator/Operator.h"
      28             : #include "compiler/translator/Types.h"
      29             : 
      30             : namespace sh
      31             : {
      32             : 
      33             : class TDiagnostics;
      34             : 
      35             : class TIntermTraverser;
      36             : class TIntermAggregate;
      37             : class TIntermBlock;
      38             : class TIntermDeclaration;
      39             : class TIntermFunctionDefinition;
      40             : class TIntermSwizzle;
      41             : class TIntermBinary;
      42             : class TIntermUnary;
      43             : class TIntermConstantUnion;
      44             : class TIntermTernary;
      45             : class TIntermIfElse;
      46             : class TIntermSwitch;
      47             : class TIntermCase;
      48             : class TIntermTyped;
      49             : class TIntermSymbol;
      50             : class TIntermLoop;
      51             : class TInfoSink;
      52             : class TInfoSinkBase;
      53             : class TIntermRaw;
      54             : class TIntermBranch;
      55             : 
      56             : class TSymbolTable;
      57             : class TFunction;
      58             : 
      59             : // Encapsulate an identifier string and track whether it is coming from the original shader code
      60             : // (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
      61           0 : class TName
      62             : {
      63             :   public:
      64             :     POOL_ALLOCATOR_NEW_DELETE();
      65           0 :     explicit TName(const TString &name) : mName(name), mIsInternal(false) {}
      66           0 :     TName() : mName(), mIsInternal(false) {}
      67           0 :     TName(const TName &) = default;
      68             :     TName &operator=(const TName &) = default;
      69             : 
      70           0 :     const TString &getString() const { return mName; }
      71           0 :     void setString(const TString &string) { mName = string; }
      72           0 :     bool isInternal() const { return mIsInternal; }
      73           0 :     void setInternal(bool isInternal) { mIsInternal = isInternal; }
      74             : 
      75             :   private:
      76             :     TString mName;
      77             :     bool mIsInternal;
      78             : };
      79             : 
      80             : //
      81             : // Base class for the tree nodes
      82             : //
      83             : class TIntermNode : angle::NonCopyable
      84             : {
      85             :   public:
      86           0 :     POOL_ALLOCATOR_NEW_DELETE();
      87           0 :     TIntermNode()
      88           0 :     {
      89             :         // TODO: Move this to TSourceLoc constructor
      90             :         // after getting rid of TPublicType.
      91           0 :         mLine.first_file = mLine.last_file = 0;
      92           0 :         mLine.first_line = mLine.last_line = 0;
      93           0 :     }
      94           0 :     virtual ~TIntermNode() { }
      95             : 
      96           0 :     const TSourceLoc &getLine() const { return mLine; }
      97           0 :     void setLine(const TSourceLoc &l) { mLine = l; }
      98             : 
      99             :     virtual void traverse(TIntermTraverser *) = 0;
     100           0 :     virtual TIntermTyped *getAsTyped() { return 0; }
     101           0 :     virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
     102           0 :     virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
     103           0 :     virtual TIntermAggregate *getAsAggregate() { return 0; }
     104           0 :     virtual TIntermBlock *getAsBlock() { return nullptr; }
     105           0 :     virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
     106           0 :     virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
     107           0 :     virtual TIntermBinary *getAsBinaryNode() { return 0; }
     108           0 :     virtual TIntermUnary *getAsUnaryNode() { return 0; }
     109           0 :     virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
     110           0 :     virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
     111           0 :     virtual TIntermSwitch *getAsSwitchNode() { return 0; }
     112           0 :     virtual TIntermCase *getAsCaseNode() { return 0; }
     113           0 :     virtual TIntermSymbol *getAsSymbolNode() { return 0; }
     114           0 :     virtual TIntermLoop *getAsLoopNode() { return 0; }
     115           0 :     virtual TIntermRaw *getAsRawNode() { return 0; }
     116           0 :     virtual TIntermBranch *getAsBranchNode() { return 0; }
     117             : 
     118             :     // Replace a child node. Return true if |original| is a child
     119             :     // node and it is replaced; otherwise, return false.
     120             :     virtual bool replaceChildNode(
     121             :         TIntermNode *original, TIntermNode *replacement) = 0;
     122             : 
     123             :   protected:
     124             :     TSourceLoc mLine;
     125             : };
     126             : 
     127             : //
     128             : // This is just to help yacc.
     129             : //
     130             : struct TIntermNodePair
     131             : {
     132             :     TIntermNode *node1;
     133             :     TIntermNode *node2;
     134             : };
     135             : 
     136             : //
     137             : // Intermediate class for nodes that have a type.
     138             : //
     139           0 : class TIntermTyped : public TIntermNode
     140             : {
     141             :   public:
     142           0 :     TIntermTyped(const TType &t) : mType(t)  { }
     143             : 
     144             :     virtual TIntermTyped *deepCopy() const = 0;
     145             : 
     146           0 :     TIntermTyped *getAsTyped() override { return this; }
     147             : 
     148             :     virtual bool hasSideEffects() const = 0;
     149             : 
     150           0 :     void setType(const TType &t) { mType = t; }
     151             :     void setTypePreservePrecision(const TType &t);
     152           0 :     const TType &getType() const { return mType; }
     153           0 :     TType *getTypePointer() { return &mType; }
     154             : 
     155           0 :     TBasicType getBasicType() const { return mType.getBasicType(); }
     156           0 :     TQualifier getQualifier() const { return mType.getQualifier(); }
     157           0 :     TPrecision getPrecision() const { return mType.getPrecision(); }
     158           0 :     TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); }
     159           0 :     int getCols() const { return mType.getCols(); }
     160           0 :     int getRows() const { return mType.getRows(); }
     161           0 :     int getNominalSize() const { return mType.getNominalSize(); }
     162           0 :     int getSecondarySize() const { return mType.getSecondarySize(); }
     163             : 
     164           0 :     bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
     165           0 :     bool isMatrix() const { return mType.isMatrix(); }
     166           0 :     bool isArray()  const { return mType.isArray(); }
     167           0 :     bool isVector() const { return mType.isVector(); }
     168           0 :     bool isScalar() const { return mType.isScalar(); }
     169           0 :     bool isScalarInt() const { return mType.isScalarInt(); }
     170             :     const char *getBasicString() const { return mType.getBasicString(); }
     171           0 :     TString getCompleteString() const { return mType.getCompleteString(); }
     172             : 
     173           0 :     unsigned int getArraySize() const { return mType.getArraySize(); }
     174             : 
     175             :     bool isConstructorWithOnlyConstantUnionParameters();
     176             : 
     177             :     static TIntermTyped *CreateIndexNode(int index);
     178             :     static TIntermTyped *CreateZero(const TType &type);
     179             : 
     180             :   protected:
     181             :     TType mType;
     182             : 
     183             :     TIntermTyped(const TIntermTyped &node);
     184             : };
     185             : 
     186             : //
     187             : // Handle for, do-while, and while loops.
     188             : //
     189             : enum TLoopType
     190             : {
     191             :     ELoopFor,
     192             :     ELoopWhile,
     193             :     ELoopDoWhile
     194             : };
     195             : 
     196           0 : class TIntermLoop : public TIntermNode
     197             : {
     198             :   public:
     199           0 :     TIntermLoop(TLoopType type,
     200             :                 TIntermNode *init,
     201             :                 TIntermTyped *cond,
     202             :                 TIntermTyped *expr,
     203             :                 TIntermBlock *body)
     204           0 :         : mType(type), mInit(init), mCond(cond), mExpr(expr), mBody(body)
     205             :     {
     206           0 :     }
     207             : 
     208           0 :     TIntermLoop *getAsLoopNode() override { return this; }
     209             :     void traverse(TIntermTraverser *it) override;
     210             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     211             : 
     212           0 :     TLoopType getType() const { return mType; }
     213           0 :     TIntermNode *getInit() { return mInit; }
     214           0 :     TIntermTyped *getCondition() { return mCond; }
     215           0 :     TIntermTyped *getExpression() { return mExpr; }
     216           0 :     TIntermBlock *getBody() { return mBody; }
     217             : 
     218           0 :     void setCondition(TIntermTyped *condition) { mCond = condition; }
     219             :     void setExpression(TIntermTyped *expression) { mExpr = expression; }
     220           0 :     void setBody(TIntermBlock *body) { mBody = body; }
     221             : 
     222             :   protected:
     223             :     TLoopType mType;
     224             :     TIntermNode *mInit;  // for-loop initialization
     225             :     TIntermTyped *mCond; // loop exit condition
     226             :     TIntermTyped *mExpr; // for-loop expression
     227             :     TIntermBlock *mBody;  // loop body
     228             : };
     229             : 
     230             : //
     231             : // Handle break, continue, return, and kill.
     232             : //
     233           0 : class TIntermBranch : public TIntermNode
     234             : {
     235             :   public:
     236           0 :     TIntermBranch(TOperator op, TIntermTyped *e)
     237           0 :         : mFlowOp(op),
     238           0 :           mExpression(e) { }
     239             : 
     240             :     void traverse(TIntermTraverser *it) override;
     241           0 :     TIntermBranch *getAsBranchNode() override { return this; }
     242             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     243             : 
     244           0 :     TOperator getFlowOp() { return mFlowOp; }
     245           0 :     TIntermTyped* getExpression() { return mExpression; }
     246             : 
     247             : protected:
     248             :     TOperator mFlowOp;
     249             :     TIntermTyped *mExpression;  // non-zero except for "return exp;" statements
     250             : };
     251             : 
     252             : //
     253             : // Nodes that correspond to symbols or constants in the source code.
     254             : //
     255           0 : class TIntermSymbol : public TIntermTyped
     256             : {
     257             :   public:
     258             :     // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
     259             :     // If sym comes from per process globalpoolallocator, then it causes increased memory usage
     260             :     // per compile it is essential to use "symbol = sym" to assign to symbol
     261           0 :     TIntermSymbol(int id, const TString &symbol, const TType &type)
     262           0 :         : TIntermTyped(type), mId(id), mSymbol(symbol)
     263             :     {
     264           0 :     }
     265             : 
     266           0 :     TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); }
     267             : 
     268           0 :     bool hasSideEffects() const override { return false; }
     269             : 
     270           0 :     int getId() const { return mId; }
     271           0 :     const TString &getSymbol() const { return mSymbol.getString(); }
     272           0 :     const TName &getName() const { return mSymbol; }
     273             : 
     274           0 :     void setId(int newId) { mId = newId; }
     275             : 
     276           0 :     void setInternal(bool internal) { mSymbol.setInternal(internal); }
     277             : 
     278             :     void traverse(TIntermTraverser *it) override;
     279           0 :     TIntermSymbol *getAsSymbolNode() override { return this; }
     280           0 :     bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
     281             : 
     282             :   protected:
     283             :     int mId;
     284             :     TName mSymbol;
     285             : 
     286             :   private:
     287           0 :     TIntermSymbol(const TIntermSymbol &) = default;  // Note: not deleted, just private!
     288             : };
     289             : 
     290             : // A Raw node stores raw code, that the translator will insert verbatim
     291             : // into the output stream. Useful for transformation operations that make
     292             : // complex code that might not fit naturally into the GLSL model.
     293           0 : class TIntermRaw : public TIntermTyped
     294             : {
     295             :   public:
     296           0 :     TIntermRaw(const TType &type, const TString &rawText)
     297           0 :         : TIntermTyped(type),
     298           0 :           mRawText(rawText) { }
     299             :     TIntermRaw(const TIntermRaw &) = delete;
     300             : 
     301           0 :     TIntermTyped *deepCopy() const override
     302             :     {
     303           0 :         UNREACHABLE();
     304             :         return nullptr;
     305             :     }
     306             : 
     307           0 :     bool hasSideEffects() const override { return false; }
     308             : 
     309           0 :     TString getRawText() const { return mRawText; }
     310             : 
     311             :     void traverse(TIntermTraverser *it) override;
     312             : 
     313           0 :     TIntermRaw *getAsRawNode() override { return this; }
     314           0 :     bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
     315             : 
     316             :   protected:
     317             :     TString mRawText;
     318             : };
     319             : 
     320             : // Constant folded node.
     321             : // Note that nodes may be constant folded and not be constant expressions with the EvqConst
     322             : // qualifier. This happens for example when the following expression is processed:
     323             : // "true ? 1.0 : non_constant"
     324             : // Other nodes than TIntermConstantUnion may also be constant expressions.
     325             : //
     326           0 : class TIntermConstantUnion : public TIntermTyped
     327             : {
     328             :   public:
     329           0 :     TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
     330           0 :         : TIntermTyped(type), mUnionArrayPointer(unionPointer)
     331             :     {
     332           0 :         ASSERT(unionPointer);
     333           0 :     }
     334             : 
     335           0 :     TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
     336             : 
     337           0 :     bool hasSideEffects() const override { return false; }
     338             : 
     339           0 :     const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
     340             : 
     341           0 :     int getIConst(size_t index) const
     342             :     {
     343           0 :         return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
     344             :     }
     345           0 :     unsigned int getUConst(size_t index) const
     346             :     {
     347           0 :         return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
     348             :     }
     349             :     float getFConst(size_t index) const
     350             :     {
     351             :         return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
     352             :     }
     353           0 :     bool getBConst(size_t index) const
     354             :     {
     355           0 :         return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
     356             :     }
     357             : 
     358           0 :     void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
     359             :     {
     360           0 :         ASSERT(safeConstantUnion);
     361             :         // Previous union pointer freed on pool deallocation.
     362           0 :         mUnionArrayPointer = safeConstantUnion;
     363           0 :     }
     364             : 
     365           0 :     TIntermConstantUnion *getAsConstantUnion() override { return this; }
     366             :     void traverse(TIntermTraverser *it) override;
     367           0 :     bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
     368             : 
     369             :     TConstantUnion *foldBinary(TOperator op,
     370             :                                TIntermConstantUnion *rightNode,
     371             :                                TDiagnostics *diagnostics,
     372             :                                const TSourceLoc &line);
     373             :     const TConstantUnion *foldIndexing(int index);
     374             :     TConstantUnion *foldUnaryNonComponentWise(TOperator op);
     375             :     TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
     376             : 
     377             :     static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
     378             :     static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
     379             :                                                 TDiagnostics *diagnostics);
     380             : 
     381             :   protected:
     382             :     // Same data may be shared between multiple constant unions, so it can't be modified.
     383             :     const TConstantUnion *mUnionArrayPointer;
     384             : 
     385             :   private:
     386             :     typedef float(*FloatTypeUnaryFunc) (float);
     387             :     void foldFloatTypeUnary(const TConstantUnion &parameter,
     388             :                             FloatTypeUnaryFunc builtinFunc,
     389             :                             TConstantUnion *result) const;
     390             : 
     391             :     TIntermConstantUnion(const TIntermConstantUnion &node);  // Note: not deleted, just private!
     392             : };
     393             : 
     394             : //
     395             : // Intermediate class for node types that hold operators.
     396             : //
     397           0 : class TIntermOperator : public TIntermTyped
     398             : {
     399             :   public:
     400           0 :     TOperator getOp() const { return mOp; }
     401             : 
     402             :     bool isAssignment() const;
     403             :     bool isMultiplication() const;
     404             :     bool isConstructor() const;
     405             : 
     406           0 :     bool hasSideEffects() const override { return isAssignment(); }
     407             : 
     408             :   protected:
     409           0 :     TIntermOperator(TOperator op)
     410           0 :         : TIntermTyped(TType(EbtFloat, EbpUndefined)),
     411           0 :           mOp(op) {}
     412             :     TIntermOperator(TOperator op, const TType &type)
     413             :         : TIntermTyped(type),
     414             :           mOp(op) {}
     415             : 
     416           0 :     TIntermOperator(const TIntermOperator &) = default;
     417             : 
     418             :     TOperator mOp;
     419             : };
     420             : 
     421             : // Node for vector swizzles.
     422           0 : class TIntermSwizzle : public TIntermTyped
     423             : {
     424             :   public:
     425             :     // This constructor determines the type of the node based on the operand.
     426             :     TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
     427             : 
     428           0 :     TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
     429             : 
     430           0 :     TIntermSwizzle *getAsSwizzleNode() override { return this; };
     431             :     void traverse(TIntermTraverser *it) override;
     432             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     433             : 
     434           0 :     bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
     435             : 
     436           0 :     TIntermTyped *getOperand() { return mOperand; }
     437             :     void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
     438             : 
     439             :     bool hasDuplicateOffsets() const;
     440             : 
     441             :     TIntermTyped *fold();
     442             : 
     443             :   protected:
     444             :     TIntermTyped *mOperand;
     445             :     TVector<int> mSwizzleOffsets;
     446             : 
     447             :   private:
     448             :     void promote();
     449             : 
     450             :     TIntermSwizzle(const TIntermSwizzle &node);  // Note: not deleted, just private!
     451             : };
     452             : 
     453             : //
     454             : // Nodes for all the basic binary math operators.
     455             : //
     456           0 : class TIntermBinary : public TIntermOperator
     457             : {
     458             :   public:
     459             :     // This constructor determines the type of the binary node based on the operands and op.
     460             :     TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
     461             : 
     462           0 :     TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
     463             : 
     464             :     static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
     465             :     static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
     466             :     static TQualifier GetCommaQualifier(int shaderVersion,
     467             :                                         const TIntermTyped *left,
     468             :                                         const TIntermTyped *right);
     469             : 
     470           0 :     TIntermBinary *getAsBinaryNode() override { return this; };
     471             :     void traverse(TIntermTraverser *it) override;
     472             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     473             : 
     474           0 :     bool hasSideEffects() const override
     475             :     {
     476           0 :         return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
     477             :     }
     478             : 
     479           0 :     TIntermTyped *getLeft() const { return mLeft; }
     480           0 :     TIntermTyped *getRight() const { return mRight; }
     481             :     TIntermTyped *fold(TDiagnostics *diagnostics);
     482             : 
     483           0 :     void setAddIndexClamp() { mAddIndexClamp = true; }
     484           0 :     bool getAddIndexClamp() { return mAddIndexClamp; }
     485             : 
     486             :   protected:
     487             :     TIntermTyped* mLeft;
     488             :     TIntermTyped* mRight;
     489             : 
     490             :     // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
     491             :     bool mAddIndexClamp;
     492             : 
     493             :   private:
     494             :     void promote();
     495             : 
     496             :     TIntermBinary(const TIntermBinary &node);  // Note: not deleted, just private!
     497             : };
     498             : 
     499             : //
     500             : // Nodes for unary math operators.
     501             : //
     502           0 : class TIntermUnary : public TIntermOperator
     503             : {
     504             :   public:
     505             :     TIntermUnary(TOperator op, TIntermTyped *operand);
     506             : 
     507           0 :     TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
     508             : 
     509             :     void traverse(TIntermTraverser *it) override;
     510           0 :     TIntermUnary *getAsUnaryNode() override { return this; }
     511             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     512             : 
     513           0 :     bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
     514             : 
     515           0 :     TIntermTyped *getOperand() { return mOperand; }
     516             :     TIntermTyped *fold(TDiagnostics *diagnostics);
     517             : 
     518           0 :     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
     519           0 :     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
     520             : 
     521             :   protected:
     522             :     TIntermTyped *mOperand;
     523             : 
     524             :     // If set to true, replace the built-in function call with an emulated one
     525             :     // to work around driver bugs.
     526             :     bool mUseEmulatedFunction;
     527             : 
     528             :   private:
     529             :     void promote();
     530             : 
     531             :     TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
     532             : };
     533             : 
     534           0 : class TFunctionSymbolInfo
     535             : {
     536             :   public:
     537             :     POOL_ALLOCATOR_NEW_DELETE();
     538           0 :     TFunctionSymbolInfo() : mId(0) {}
     539             : 
     540           0 :     TFunctionSymbolInfo(const TFunctionSymbolInfo &) = default;
     541             :     TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &) = default;
     542             : 
     543             :     void setFromFunction(const TFunction &function);
     544             : 
     545           0 :     void setNameObj(const TName &name) { mName = name; }
     546           0 :     const TName &getNameObj() const { return mName; }
     547             : 
     548           0 :     const TString &getName() const { return mName.getString(); }
     549           0 :     void setName(const TString &name) { mName.setString(name); }
     550           0 :     bool isMain() const { return mName.getString() == "main("; }
     551             : 
     552           0 :     void setId(int functionId) { mId = functionId; }
     553           0 :     int getId() const { return mId; }
     554             :   private:
     555             :     TName mName;
     556             :     int mId;
     557             : };
     558             : 
     559             : // Node for function definitions.
     560           0 : class TIntermFunctionDefinition : public TIntermTyped
     561             : {
     562             :   public:
     563             :     // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
     564             :     // parameters.
     565           0 :     TIntermFunctionDefinition(const TType &type, TIntermAggregate *parameters, TIntermBlock *body)
     566           0 :         : TIntermTyped(type), mParameters(parameters), mBody(body)
     567             :     {
     568           0 :         ASSERT(parameters != nullptr);
     569           0 :         ASSERT(body != nullptr);
     570           0 :     }
     571             : 
     572           0 :     TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
     573             :     void traverse(TIntermTraverser *it) override;
     574             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     575             : 
     576           0 :     TIntermTyped *deepCopy() const override
     577             :     {
     578           0 :         UNREACHABLE();
     579             :         return nullptr;
     580             :     }
     581           0 :     bool hasSideEffects() const override
     582             :     {
     583           0 :         UNREACHABLE();
     584             :         return true;
     585             :     }
     586             : 
     587           0 :     TIntermAggregate *getFunctionParameters() const { return mParameters; }
     588           0 :     TIntermBlock *getBody() const { return mBody; }
     589             : 
     590           0 :     TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
     591           0 :     const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
     592             : 
     593             :   private:
     594             :     TIntermAggregate *mParameters;
     595             :     TIntermBlock *mBody;
     596             : 
     597             :     TFunctionSymbolInfo mFunctionInfo;
     598             : };
     599             : 
     600             : typedef TVector<TIntermNode *> TIntermSequence;
     601             : typedef TVector<int> TQualifierList;
     602             : 
     603             : // Interface for node classes that have an arbitrarily sized set of children.
     604             : class TIntermAggregateBase
     605             : {
     606             :   public:
     607           0 :     virtual ~TIntermAggregateBase() {}
     608             : 
     609             :     virtual TIntermSequence *getSequence()             = 0;
     610             :     virtual const TIntermSequence *getSequence() const = 0;
     611             : 
     612             :     bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
     613             :     bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
     614             : 
     615             :   protected:
     616           0 :     TIntermAggregateBase() {}
     617             : 
     618             :     bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
     619             : };
     620             : 
     621             : //
     622             : // Nodes that operate on an arbitrary sized set of children.
     623             : //
     624             : class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
     625             : {
     626             :   public:
     627           0 :     TIntermAggregate()
     628           0 :         : TIntermOperator(EOpNull),
     629             :           mUserDefined(false),
     630             :           mUseEmulatedFunction(false),
     631           0 :           mGotPrecisionFromChildren(false)
     632             :     {
     633           0 :     }
     634           0 :     TIntermAggregate(TOperator op)
     635           0 :         : TIntermOperator(op),
     636             :           mUserDefined(false),
     637             :           mUseEmulatedFunction(false),
     638           0 :           mGotPrecisionFromChildren(false)
     639             :     {
     640           0 :     }
     641           0 :     ~TIntermAggregate() { }
     642             : 
     643             :     // Note: only supported for nodes that can be a part of an expression.
     644           0 :     TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
     645             : 
     646           0 :     void setOp(TOperator op) { mOp = op; }
     647             : 
     648           0 :     TIntermAggregate *getAsAggregate() override { return this; }
     649             :     void traverse(TIntermTraverser *it) override;
     650             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     651             : 
     652             :     // Conservatively assume function calls and other aggregate operators have side-effects
     653           0 :     bool hasSideEffects() const override { return true; }
     654             :     TIntermTyped *fold(TDiagnostics *diagnostics);
     655             : 
     656           0 :     TIntermSequence *getSequence() override { return &mSequence; }
     657           0 :     const TIntermSequence *getSequence() const override { return &mSequence; }
     658             : 
     659           0 :     void setUserDefined() { mUserDefined = true; }
     660           0 :     bool isUserDefined() const { return mUserDefined; }
     661             : 
     662           0 :     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
     663           0 :     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
     664             : 
     665             :     bool areChildrenConstQualified();
     666             :     void setPrecisionFromChildren();
     667             :     void setBuiltInFunctionPrecision();
     668             : 
     669             :     // Returns true if changing parameter precision may affect the return value.
     670           0 :     bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
     671             : 
     672           0 :     TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
     673           0 :     const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
     674             : 
     675             :   protected:
     676             :     TIntermSequence mSequence;
     677             :     bool mUserDefined; // used for user defined function names
     678             : 
     679             :     // If set to true, replace the built-in function call with an emulated one
     680             :     // to work around driver bugs.
     681             :     bool mUseEmulatedFunction;
     682             : 
     683             :     bool mGotPrecisionFromChildren;
     684             : 
     685             :     TFunctionSymbolInfo mFunctionInfo;
     686             : 
     687             :   private:
     688             :     TIntermAggregate(const TIntermAggregate &node);  // note: not deleted, just private!
     689             : };
     690             : 
     691             : // A list of statements. Either the root node which contains declarations and function definitions,
     692             : // or a block that can be marked with curly braces {}.
     693             : class TIntermBlock : public TIntermNode, public TIntermAggregateBase
     694             : {
     695             :   public:
     696           0 :     TIntermBlock() : TIntermNode() {}
     697           0 :     ~TIntermBlock() {}
     698             : 
     699           0 :     TIntermBlock *getAsBlock() override { return this; }
     700             :     void traverse(TIntermTraverser *it) override;
     701             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     702             : 
     703             :     // Only intended for initially building the block.
     704             :     void appendStatement(TIntermNode *statement);
     705             : 
     706           0 :     TIntermSequence *getSequence() override { return &mStatements; }
     707           0 :     const TIntermSequence *getSequence() const override { return &mStatements; }
     708             : 
     709             :   protected:
     710             :     TIntermSequence mStatements;
     711             : };
     712             : 
     713             : // Struct, interface block or variable declaration. Can contain multiple variable declarators.
     714             : class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
     715             : {
     716             :   public:
     717           0 :     TIntermDeclaration() : TIntermNode() {}
     718           0 :     ~TIntermDeclaration() {}
     719             : 
     720           0 :     TIntermDeclaration *getAsDeclarationNode() override { return this; }
     721             :     void traverse(TIntermTraverser *it) override;
     722             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     723             : 
     724             :     // Only intended for initially building the declaration.
     725             :     // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
     726             :     // EOpInitialize.
     727             :     void appendDeclarator(TIntermTyped *declarator);
     728             : 
     729           0 :     TIntermSequence *getSequence() override { return &mDeclarators; }
     730           0 :     const TIntermSequence *getSequence() const override { return &mDeclarators; }
     731             :   protected:
     732             :     TIntermSequence mDeclarators;
     733             : };
     734             : 
     735             : // For ternary operators like a ? b : c.
     736           0 : class TIntermTernary : public TIntermTyped
     737             : {
     738             :   public:
     739             :     TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
     740             : 
     741             :     void traverse(TIntermTraverser *it) override;
     742             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     743             : 
     744           0 :     TIntermTyped *getCondition() const { return mCondition; }
     745           0 :     TIntermTyped *getTrueExpression() const { return mTrueExpression; }
     746           0 :     TIntermTyped *getFalseExpression() const { return mFalseExpression; }
     747           0 :     TIntermTernary *getAsTernaryNode() override { return this; }
     748             : 
     749           0 :     TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
     750             : 
     751           0 :     bool hasSideEffects() const override
     752             :     {
     753           0 :         return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
     754           0 :                mFalseExpression->hasSideEffects();
     755             :     }
     756             : 
     757             :     static TQualifier DetermineQualifier(TIntermTyped *cond,
     758             :                                          TIntermTyped *trueExpression,
     759             :                                          TIntermTyped *falseExpression);
     760             : 
     761             :   private:
     762             :     TIntermTernary(const TIntermTernary &node);  // Note: not deleted, just private!
     763             : 
     764             :     TIntermTyped *mCondition;
     765             :     TIntermTyped *mTrueExpression;
     766             :     TIntermTyped *mFalseExpression;
     767             : };
     768             : 
     769           0 : class TIntermIfElse : public TIntermNode
     770             : {
     771             :   public:
     772           0 :     TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB)
     773           0 :         : TIntermNode(), mCondition(cond), mTrueBlock(trueB), mFalseBlock(falseB)
     774             :     {
     775           0 :     }
     776             : 
     777             :     void traverse(TIntermTraverser *it) override;
     778             :     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
     779             : 
     780           0 :     TIntermTyped *getCondition() const { return mCondition; }
     781           0 :     TIntermBlock *getTrueBlock() const { return mTrueBlock; }
     782           0 :     TIntermBlock *getFalseBlock() const { return mFalseBlock; }
     783           0 :     TIntermIfElse *getAsIfElseNode() override { return this; }
     784             : 
     785             :   protected:
     786             :     TIntermTyped *mCondition;
     787             :     TIntermBlock *mTrueBlock;
     788             :     TIntermBlock *mFalseBlock;
     789             : };
     790             : 
     791             : //
     792             : // Switch statement.
     793             : //
     794           0 : class TIntermSwitch : public TIntermNode
     795             : {
     796             :   public:
     797           0 :     TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList)
     798           0 :         : TIntermNode(), mInit(init), mStatementList(statementList)
     799             :     {
     800           0 :     }
     801             : 
     802             :     void traverse(TIntermTraverser *it) override;
     803             :     bool replaceChildNode(
     804             :         TIntermNode *original, TIntermNode *replacement) override;
     805             : 
     806           0 :     TIntermSwitch *getAsSwitchNode() override { return this; }
     807             : 
     808           0 :     TIntermTyped *getInit() { return mInit; }
     809           0 :     TIntermBlock *getStatementList() { return mStatementList; }
     810           0 :     void setStatementList(TIntermBlock *statementList) { mStatementList = statementList; }
     811             : 
     812             :   protected:
     813             :     TIntermTyped *mInit;
     814             :     TIntermBlock *mStatementList;
     815             : };
     816             : 
     817             : //
     818             : // Case label.
     819             : //
     820           0 : class TIntermCase : public TIntermNode
     821             : {
     822             :   public:
     823           0 :     TIntermCase(TIntermTyped *condition)
     824           0 :         : TIntermNode(),
     825           0 :           mCondition(condition)
     826             :     {
     827           0 :     }
     828             : 
     829             :     void traverse(TIntermTraverser *it) override;
     830             :     bool replaceChildNode(
     831             :         TIntermNode *original, TIntermNode *replacement) override;
     832             : 
     833           0 :     TIntermCase *getAsCaseNode() override { return this; }
     834             : 
     835           0 :     bool hasCondition() const { return mCondition != nullptr; }
     836           0 :     TIntermTyped *getCondition() const { return mCondition; }
     837             : 
     838             :   protected:
     839             :     TIntermTyped *mCondition;
     840             : };
     841             : 
     842             : enum Visit
     843             : {
     844             :     PreVisit,
     845             :     InVisit,
     846             :     PostVisit
     847             : };
     848             : 
     849             : //
     850             : // For traversing the tree.  User should derive from this class overriding the visit functions,
     851             : // and then pass an object of the subclass to a traverse method of a node.
     852             : //
     853             : // The traverse*() functions may also be overridden do other bookkeeping on the tree to provide
     854             : // contextual information to the visit functions, such as whether the node is the target of an
     855             : // assignment.
     856             : //
     857             : // When using this, just fill in the methods for nodes you want visited.
     858             : // Return false from a pre-visit to skip visiting that node's subtree.
     859             : //
     860             : class TIntermTraverser : angle::NonCopyable
     861             : {
     862             :   public:
     863           0 :     POOL_ALLOCATOR_NEW_DELETE();
     864             :     TIntermTraverser(bool preVisit, bool inVisit, bool postVisit);
     865             :     virtual ~TIntermTraverser();
     866             : 
     867           0 :     virtual void visitSymbol(TIntermSymbol *node) {}
     868           0 :     virtual void visitRaw(TIntermRaw *node) {}
     869           0 :     virtual void visitConstantUnion(TIntermConstantUnion *node) {}
     870           0 :     virtual bool visitSwizzle(Visit visit, TIntermSwizzle *node) { return true; }
     871           0 :     virtual bool visitBinary(Visit visit, TIntermBinary *node) { return true; }
     872           0 :     virtual bool visitUnary(Visit visit, TIntermUnary *node) { return true; }
     873           0 :     virtual bool visitTernary(Visit visit, TIntermTernary *node) { return true; }
     874           0 :     virtual bool visitIfElse(Visit visit, TIntermIfElse *node) { return true; }
     875           0 :     virtual bool visitSwitch(Visit visit, TIntermSwitch *node) { return true; }
     876           0 :     virtual bool visitCase(Visit visit, TIntermCase *node) { return true; }
     877           0 :     virtual bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
     878             :     {
     879           0 :         return true;
     880             :     }
     881           0 :     virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
     882           0 :     virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; }
     883           0 :     virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; }
     884           0 :     virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
     885           0 :     virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
     886             : 
     887             :     // The traverse functions contain logic for iterating over the children of the node
     888             :     // and calling the visit functions in the appropriate places. They also track some
     889             :     // context that may be used by the visit functions.
     890             :     virtual void traverseSymbol(TIntermSymbol *node);
     891             :     virtual void traverseRaw(TIntermRaw *node);
     892             :     virtual void traverseConstantUnion(TIntermConstantUnion *node);
     893             :     virtual void traverseSwizzle(TIntermSwizzle *node);
     894             :     virtual void traverseBinary(TIntermBinary *node);
     895             :     virtual void traverseUnary(TIntermUnary *node);
     896             :     virtual void traverseTernary(TIntermTernary *node);
     897             :     virtual void traverseIfElse(TIntermIfElse *node);
     898             :     virtual void traverseSwitch(TIntermSwitch *node);
     899             :     virtual void traverseCase(TIntermCase *node);
     900             :     virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
     901             :     virtual void traverseAggregate(TIntermAggregate *node);
     902             :     virtual void traverseBlock(TIntermBlock *node);
     903             :     virtual void traverseDeclaration(TIntermDeclaration *node);
     904             :     virtual void traverseLoop(TIntermLoop *node);
     905             :     virtual void traverseBranch(TIntermBranch *node);
     906             : 
     907           0 :     int getMaxDepth() const { return mMaxDepth; }
     908             : 
     909             :     // Return the original name if hash function pointer is NULL;
     910             :     // otherwise return the hashed name.
     911             :     static TString hash(const TString &name, ShHashFunction64 hashFunction);
     912             : 
     913             :     // If traversers need to replace nodes, they can add the replacements in
     914             :     // mReplacements/mMultiReplacements during traversal and the user of the traverser should call
     915             :     // this function after traversal to perform them.
     916             :     void updateTree();
     917             : 
     918             :     // Start creating temporary symbols from the given temporary symbol index + 1.
     919             :     void useTemporaryIndex(unsigned int *temporaryIndex);
     920             : 
     921             :   protected:
     922           0 :     void incrementDepth(TIntermNode *current)
     923             :     {
     924           0 :         mDepth++;
     925           0 :         mMaxDepth = std::max(mMaxDepth, mDepth);
     926           0 :         mPath.push_back(current);
     927           0 :     }
     928             : 
     929           0 :     void decrementDepth()
     930             :     {
     931           0 :         mDepth--;
     932           0 :         mPath.pop_back();
     933           0 :     }
     934             : 
     935           0 :     TIntermNode *getParentNode()
     936             :     {
     937           0 :         return mPath.size() == 0 ? NULL : mPath.back();
     938             :     }
     939             : 
     940             :     // Return the nth ancestor of the node being traversed. getAncestorNode(0) == getParentNode()
     941           0 :     TIntermNode *getAncestorNode(unsigned int n)
     942             :     {
     943           0 :         if (mPath.size() > n)
     944             :         {
     945           0 :             return mPath[mPath.size() - n - 1u];
     946             :         }
     947           0 :         return nullptr;
     948             :     }
     949             : 
     950             :     void pushParentBlock(TIntermBlock *node);
     951             :     void incrementParentBlockPos();
     952             :     void popParentBlock();
     953             : 
     954             :     bool parentNodeIsBlock()
     955             :     {
     956             :         return !mParentBlockStack.empty() && getParentNode() == mParentBlockStack.back().node;
     957             :     }
     958             : 
     959             :     // To replace a single node with multiple nodes on the parent aggregate node
     960           0 :     struct NodeReplaceWithMultipleEntry
     961             :     {
     962           0 :         NodeReplaceWithMultipleEntry(TIntermAggregateBase *_parent,
     963             :                                      TIntermNode *_original,
     964             :                                      TIntermSequence _replacements)
     965           0 :             : parent(_parent), original(_original), replacements(_replacements)
     966             :         {
     967           0 :         }
     968             : 
     969             :         TIntermAggregateBase *parent;
     970             :         TIntermNode *original;
     971             :         TIntermSequence replacements;
     972             :     };
     973             : 
     974             :     // To insert multiple nodes on the parent aggregate node
     975           0 :     struct NodeInsertMultipleEntry
     976             :     {
     977           0 :         NodeInsertMultipleEntry(TIntermBlock *_parent,
     978             :                                 TIntermSequence::size_type _position,
     979             :                                 TIntermSequence _insertionsBefore,
     980             :                                 TIntermSequence _insertionsAfter)
     981           0 :             : parent(_parent),
     982             :               position(_position),
     983             :               insertionsBefore(_insertionsBefore),
     984           0 :               insertionsAfter(_insertionsAfter)
     985             :         {
     986           0 :         }
     987             : 
     988             :         TIntermBlock *parent;
     989             :         TIntermSequence::size_type position;
     990             :         TIntermSequence insertionsBefore;
     991             :         TIntermSequence insertionsAfter;
     992             :     };
     993             : 
     994             :     // Helper to insert statements in the parent block (sequence) of the node currently being traversed.
     995             :     // The statements will be inserted before the node being traversed once updateTree is called.
     996             :     // Should only be called during PreVisit or PostVisit from sequence nodes.
     997             :     // Note that inserting more than one set of nodes to the same parent node on a single updateTree call is not
     998             :     // supported.
     999             :     void insertStatementsInParentBlock(const TIntermSequence &insertions);
    1000             : 
    1001             :     // Same as above, but supports simultaneous insertion of statements before and after the node
    1002             :     // currently being traversed.
    1003             :     void insertStatementsInParentBlock(const TIntermSequence &insertionsBefore,
    1004             :                                        const TIntermSequence &insertionsAfter);
    1005             : 
    1006             :     // Helper to insert a single statement.
    1007             :     void insertStatementInParentBlock(TIntermNode *statement);
    1008             : 
    1009             :     // Helper to create a temporary symbol node with the given qualifier.
    1010             :     TIntermSymbol *createTempSymbol(const TType &type, TQualifier qualifier);
    1011             :     // Helper to create a temporary symbol node.
    1012             :     TIntermSymbol *createTempSymbol(const TType &type);
    1013             :     // Create a node that declares but doesn't initialize a temporary symbol.
    1014             :     TIntermDeclaration *createTempDeclaration(const TType &type);
    1015             :     // Create a node that initializes the current temporary symbol with initializer having the given qualifier.
    1016             :     TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
    1017             :     // Create a node that initializes the current temporary symbol with initializer.
    1018             :     TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer);
    1019             :     // Create a node that assigns rightNode to the current temporary symbol.
    1020             :     TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
    1021             :     // Increment temporary symbol index.
    1022             :     void nextTemporaryIndex();
    1023             : 
    1024             :     enum class OriginalNode
    1025             :     {
    1026             :         BECOMES_CHILD,
    1027             :         IS_DROPPED
    1028             :     };
    1029             : 
    1030             :     void clearReplacementQueue();
    1031             :     void queueReplacement(TIntermNode *original,
    1032             :                           TIntermNode *replacement,
    1033             :                           OriginalNode originalStatus);
    1034             :     void queueReplacementWithParent(TIntermNode *parent,
    1035             :                                     TIntermNode *original,
    1036             :                                     TIntermNode *replacement,
    1037             :                                     OriginalNode originalStatus);
    1038             : 
    1039             :     const bool preVisit;
    1040             :     const bool inVisit;
    1041             :     const bool postVisit;
    1042             : 
    1043             :     int mDepth;
    1044             :     int mMaxDepth;
    1045             : 
    1046             :     // All the nodes from root to the current node's parent during traversing.
    1047             :     TVector<TIntermNode *> mPath;
    1048             : 
    1049             :     bool mInGlobalScope;
    1050             : 
    1051             :     // During traversing, save all the changes that need to happen into
    1052             :     // mReplacements/mMultiReplacements, then do them by calling updateTree().
    1053             :     // Multi replacements are processed after single replacements.
    1054             :     std::vector<NodeReplaceWithMultipleEntry> mMultiReplacements;
    1055             :     std::vector<NodeInsertMultipleEntry> mInsertions;
    1056             : 
    1057             :   private:
    1058             :     // To replace a single node with another on the parent node
    1059             :     struct NodeUpdateEntry
    1060             :     {
    1061           0 :         NodeUpdateEntry(TIntermNode *_parent,
    1062             :                         TIntermNode *_original,
    1063             :                         TIntermNode *_replacement,
    1064             :                         bool _originalBecomesChildOfReplacement)
    1065           0 :             : parent(_parent),
    1066             :               original(_original),
    1067             :               replacement(_replacement),
    1068           0 :               originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement)
    1069             :         {
    1070           0 :         }
    1071             : 
    1072             :         TIntermNode *parent;
    1073             :         TIntermNode *original;
    1074             :         TIntermNode *replacement;
    1075             :         bool originalBecomesChildOfReplacement;
    1076             :     };
    1077             : 
    1078             :     struct ParentBlock
    1079             :     {
    1080           0 :         ParentBlock(TIntermBlock *nodeIn, TIntermSequence::size_type posIn)
    1081           0 :             : node(nodeIn), pos(posIn)
    1082             :         {
    1083           0 :         }
    1084             : 
    1085             :         TIntermBlock *node;
    1086             :         TIntermSequence::size_type pos;
    1087             :     };
    1088             : 
    1089             :     std::vector<NodeUpdateEntry> mReplacements;
    1090             : 
    1091             :     // All the code blocks from the root to the current node's parent during traversal.
    1092             :     std::vector<ParentBlock> mParentBlockStack;
    1093             : 
    1094             :     unsigned int *mTemporaryIndex;
    1095             : };
    1096             : 
    1097             : // Traverser parent class that tracks where a node is a destination of a write operation and so is
    1098             : // required to be an l-value.
    1099             : class TLValueTrackingTraverser : public TIntermTraverser
    1100             : {
    1101             :   public:
    1102           0 :     TLValueTrackingTraverser(bool preVisit,
    1103             :                              bool inVisit,
    1104             :                              bool postVisit,
    1105             :                              const TSymbolTable &symbolTable,
    1106             :                              int shaderVersion)
    1107           0 :         : TIntermTraverser(preVisit, inVisit, postVisit),
    1108             :           mOperatorRequiresLValue(false),
    1109             :           mInFunctionCallOutParameter(false),
    1110             :           mSymbolTable(symbolTable),
    1111           0 :           mShaderVersion(shaderVersion)
    1112             :     {
    1113           0 :     }
    1114           0 :     virtual ~TLValueTrackingTraverser() {}
    1115             : 
    1116             :     void traverseBinary(TIntermBinary *node) final;
    1117             :     void traverseUnary(TIntermUnary *node) final;
    1118             :     void traverseFunctionDefinition(TIntermFunctionDefinition *node) final;
    1119             :     void traverseAggregate(TIntermAggregate *node) final;
    1120             : 
    1121             :   protected:
    1122           0 :     bool isLValueRequiredHere() const
    1123             :     {
    1124           0 :         return mOperatorRequiresLValue || mInFunctionCallOutParameter;
    1125             :     }
    1126             : 
    1127             :     // Return true if the prototype or definition of the function being called has been encountered
    1128             :     // during traversal.
    1129             :     bool isInFunctionMap(const TIntermAggregate *callNode) const;
    1130             : 
    1131             :   private:
    1132             :     // Track whether an l-value is required in the node that is currently being traversed by the
    1133             :     // surrounding operator.
    1134             :     // Use isLValueRequiredHere to check all conditions which require an l-value.
    1135           0 :     void setOperatorRequiresLValue(bool lValueRequired)
    1136             :     {
    1137           0 :         mOperatorRequiresLValue = lValueRequired;
    1138           0 :     }
    1139           0 :     bool operatorRequiresLValue() const { return mOperatorRequiresLValue; }
    1140             : 
    1141             :     // Add a function encountered during traversal to the function map.
    1142             :     void addToFunctionMap(const TName &name, TIntermSequence *paramSequence);
    1143             : 
    1144             :     // Return the parameters sequence from the function definition or prototype.
    1145             :     TIntermSequence *getFunctionParameters(const TIntermAggregate *callNode);
    1146             : 
    1147             :     // Track whether an l-value is required inside a function call.
    1148             :     void setInFunctionCallOutParameter(bool inOutParameter);
    1149             :     bool isInFunctionCallOutParameter() const;
    1150             : 
    1151             :     bool mOperatorRequiresLValue;
    1152             :     bool mInFunctionCallOutParameter;
    1153             : 
    1154             :     struct TNameComparator
    1155             :     {
    1156           0 :         bool operator()(const TName &a, const TName &b) const
    1157             :         {
    1158           0 :             int compareResult = a.getString().compare(b.getString());
    1159           0 :             if (compareResult != 0)
    1160           0 :                 return compareResult < 0;
    1161             :             // Internal functions may have same names as non-internal functions.
    1162           0 :             return !a.isInternal() && b.isInternal();
    1163             :         }
    1164             :     };
    1165             : 
    1166             :     // Map from mangled function names to their parameter sequences
    1167             :     TMap<TName, TIntermSequence *, TNameComparator> mFunctionMap;
    1168             : 
    1169             :     const TSymbolTable &mSymbolTable;
    1170             :     const int mShaderVersion;
    1171             : };
    1172             : 
    1173             : //
    1174             : // For traversing the tree, and computing max depth.
    1175             : // Takes a maximum depth limit to prevent stack overflow.
    1176             : //
    1177           0 : class TMaxDepthTraverser : public TIntermTraverser
    1178             : {
    1179             :   public:
    1180           0 :     POOL_ALLOCATOR_NEW_DELETE();
    1181           0 :     TMaxDepthTraverser(int depthLimit)
    1182           0 :         : TIntermTraverser(true, true, false),
    1183           0 :           mDepthLimit(depthLimit) { }
    1184             : 
    1185           0 :     bool visitBinary(Visit, TIntermBinary *) override { return depthCheck(); }
    1186           0 :     bool visitUnary(Visit, TIntermUnary *) override { return depthCheck(); }
    1187           0 :     bool visitTernary(Visit, TIntermTernary *) override { return depthCheck(); }
    1188           0 :     bool visitIfElse(Visit, TIntermIfElse *) override { return depthCheck(); }
    1189           0 :     bool visitAggregate(Visit, TIntermAggregate *) override { return depthCheck(); }
    1190           0 :     bool visitBlock(Visit, TIntermBlock *) override { return depthCheck(); }
    1191           0 :     bool visitLoop(Visit, TIntermLoop *) override { return depthCheck(); }
    1192           0 :     bool visitBranch(Visit, TIntermBranch *) override { return depthCheck(); }
    1193             : 
    1194             :   protected:
    1195           0 :     bool depthCheck() const { return mMaxDepth < mDepthLimit; }
    1196             : 
    1197             :     int mDepthLimit;
    1198             : };
    1199             : 
    1200             : }  // namespace sh
    1201             : 
    1202             : #endif  // COMPILER_TRANSLATOR_INTERMNODE_H_

Generated by: LCOV version 1.13