tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

IntermNode.h (37176B)


      1 //
      2 // Copyright 2002 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/ImmutableString.h"
     28 #include "compiler/translator/Operator_autogen.h"
     29 #include "compiler/translator/SymbolUniqueId.h"
     30 #include "compiler/translator/Types.h"
     31 #include "compiler/translator/tree_util/Visit.h"
     32 
     33 namespace sh
     34 {
     35 
     36 class TDiagnostics;
     37 
     38 class TIntermTraverser;
     39 class TIntermAggregate;
     40 class TIntermBlock;
     41 class TIntermGlobalQualifierDeclaration;
     42 class TIntermDeclaration;
     43 class TIntermFunctionPrototype;
     44 class TIntermFunctionDefinition;
     45 class TIntermSwizzle;
     46 class TIntermBinary;
     47 class TIntermUnary;
     48 class TIntermConstantUnion;
     49 class TIntermTernary;
     50 class TIntermIfElse;
     51 class TIntermSwitch;
     52 class TIntermCase;
     53 class TIntermTyped;
     54 class TIntermSymbol;
     55 class TIntermLoop;
     56 class TInfoSink;
     57 class TInfoSinkBase;
     58 class TIntermBranch;
     59 class TIntermPreprocessorDirective;
     60 
     61 class TSymbolTable;
     62 class TFunction;
     63 class TVariable;
     64 
     65 //
     66 // Base class for the tree nodes
     67 //
     68 class TIntermNode : angle::NonCopyable
     69 {
     70  public:
     71    POOL_ALLOCATOR_NEW_DELETE
     72    TIntermNode()
     73    {
     74        // TODO: Move this to TSourceLoc constructor
     75        // after getting rid of TPublicType.
     76        mLine.first_file = mLine.last_file = 0;
     77        mLine.first_line = mLine.last_line = 0;
     78    }
     79    virtual ~TIntermNode() {}
     80 
     81    const TSourceLoc &getLine() const { return mLine; }
     82    void setLine(const TSourceLoc &l) { mLine = l; }
     83 
     84    virtual void traverse(TIntermTraverser *it);
     85    virtual bool visit(Visit visit, TIntermTraverser *it) = 0;
     86 
     87    virtual TIntermTyped *getAsTyped() { return nullptr; }
     88    virtual TIntermConstantUnion *getAsConstantUnion() { return nullptr; }
     89    virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
     90    virtual TIntermAggregate *getAsAggregate() { return nullptr; }
     91    virtual TIntermBlock *getAsBlock() { return nullptr; }
     92    virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; }
     93    virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode()
     94    {
     95        return nullptr;
     96    }
     97    virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
     98    virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
     99    virtual TIntermBinary *getAsBinaryNode() { return nullptr; }
    100    virtual TIntermUnary *getAsUnaryNode() { return nullptr; }
    101    virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
    102    virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
    103    virtual TIntermSwitch *getAsSwitchNode() { return nullptr; }
    104    virtual TIntermCase *getAsCaseNode() { return nullptr; }
    105    virtual TIntermSymbol *getAsSymbolNode() { return nullptr; }
    106    virtual TIntermLoop *getAsLoopNode() { return nullptr; }
    107    virtual TIntermBranch *getAsBranchNode() { return nullptr; }
    108    virtual TIntermPreprocessorDirective *getAsPreprocessorDirective() { return nullptr; }
    109 
    110    virtual TIntermNode *deepCopy() const = 0;
    111 
    112    virtual size_t getChildCount() const                  = 0;
    113    virtual TIntermNode *getChildNode(size_t index) const = 0;
    114    // Replace a child node. Return true if |original| is a child
    115    // node and it is replaced; otherwise, return false.
    116    virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0;
    117 
    118  protected:
    119    TSourceLoc mLine;
    120 };
    121 
    122 //
    123 // This is just to help yacc.
    124 //
    125 struct TIntermNodePair
    126 {
    127    TIntermNode *node1;
    128    TIntermNode *node2;
    129 };
    130 
    131 //
    132 // Intermediate class for nodes that have a type.
    133 //
    134 class TIntermTyped : public TIntermNode
    135 {
    136  public:
    137    TIntermTyped();
    138 
    139    virtual TIntermTyped *deepCopy() const override = 0;
    140 
    141    TIntermTyped *getAsTyped() override { return this; }
    142 
    143    virtual TIntermTyped *fold(TDiagnostics *diagnostics) { return this; }
    144 
    145    // getConstantValue() returns the constant value that this node represents, if any. It
    146    // should only be used after nodes have been replaced with their folded versions returned
    147    // from fold(). hasConstantValue() returns true if getConstantValue() will return a value.
    148    virtual bool hasConstantValue() const;
    149    virtual bool isConstantNullValue() const;
    150    virtual const TConstantUnion *getConstantValue() const;
    151 
    152    // True if executing the expression represented by this node affects state, like values of
    153    // variables. False if the executing the expression only computes its return value without
    154    // affecting state. May return true conservatively.
    155    virtual bool hasSideEffects() const = 0;
    156 
    157    virtual const TType &getType() const = 0;
    158 
    159    // Derive the precision of the node based on its children's.
    160    virtual TPrecision derivePrecision() const;
    161    // Set precision of the current node and propagate it to any child node that doesn't have
    162    // precision.  This should be the case only for TIntermConstantUnion nodes as every other node
    163    // would already need to have its precision specified or derived.
    164    virtual void propagatePrecision(TPrecision precision);
    165 
    166    TBasicType getBasicType() const { return getType().getBasicType(); }
    167    TQualifier getQualifier() const { return getType().getQualifier(); }
    168    TPrecision getPrecision() const { return getType().getPrecision(); }
    169    TMemoryQualifier getMemoryQualifier() const { return getType().getMemoryQualifier(); }
    170    uint8_t getCols() const { return getType().getCols(); }
    171    uint8_t getRows() const { return getType().getRows(); }
    172    uint8_t getNominalSize() const { return getType().getNominalSize(); }
    173    uint8_t getSecondarySize() const { return getType().getSecondarySize(); }
    174 
    175    bool isInterfaceBlock() const { return getType().isInterfaceBlock(); }
    176    bool isMatrix() const { return getType().isMatrix(); }
    177    bool isArray() const { return getType().isArray(); }
    178    bool isVector() const { return getType().isVector(); }
    179    bool isScalar() const { return getType().isScalar(); }
    180    bool isScalarInt() const { return getType().isScalarInt(); }
    181    const char *getBasicString() const { return getType().getBasicString(); }
    182 
    183    unsigned int getOutermostArraySize() const { return getType().getOutermostArraySize(); }
    184 
    185    // After every transformation is done and just before outputting the tree (i.e. when the tree
    186    // nodes are no longer going to change), the tree is traversed to gather some information to be
    187    // stored in the intermediate nodes:
    188    //
    189    // - Precise-ness, which is set for arithmetic nodes that are involved in the calculation of a
    190    //   value assigned to a |precise| variable.
    191    void setIsPrecise() { mIsPrecise = true; }
    192    bool isPrecise() const { return mIsPrecise; }
    193 
    194  protected:
    195    TIntermTyped(const TIntermTyped &node);
    196 
    197    bool mIsPrecise;
    198 };
    199 
    200 //
    201 // Handle for, do-while, and while loops.
    202 //
    203 enum TLoopType
    204 {
    205    ELoopFor,
    206    ELoopWhile,
    207    ELoopDoWhile
    208 };
    209 
    210 class TIntermLoop : public TIntermNode
    211 {
    212  public:
    213    TIntermLoop(TLoopType type,
    214                TIntermNode *init,
    215                TIntermTyped *cond,
    216                TIntermTyped *expr,
    217                TIntermBlock *body);
    218 
    219    TIntermLoop *getAsLoopNode() override { return this; }
    220    void traverse(TIntermTraverser *it) final;
    221    bool visit(Visit visit, TIntermTraverser *it) final;
    222 
    223    size_t getChildCount() const final;
    224    TIntermNode *getChildNode(size_t index) const final;
    225    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    226 
    227    TLoopType getType() const { return mType; }
    228    TIntermNode *getInit() { return mInit; }
    229    TIntermTyped *getCondition() { return mCond; }
    230    TIntermTyped *getExpression() { return mExpr; }
    231    TIntermBlock *getBody() { return mBody; }
    232 
    233    void setInit(TIntermNode *init) { mInit = init; }
    234    void setCondition(TIntermTyped *condition) { mCond = condition; }
    235    void setExpression(TIntermTyped *expression) { mExpr = expression; }
    236    void setBody(TIntermBlock *body) { mBody = body; }
    237 
    238    virtual TIntermLoop *deepCopy() const override { return new TIntermLoop(*this); }
    239 
    240  protected:
    241    TLoopType mType;
    242    TIntermNode *mInit;   // for-loop initialization
    243    TIntermTyped *mCond;  // loop exit condition
    244    TIntermTyped *mExpr;  // for-loop expression
    245    TIntermBlock *mBody;  // loop body
    246 
    247  private:
    248    TIntermLoop(const TIntermLoop &);
    249 };
    250 
    251 //
    252 // Handle break, continue, return, and kill.
    253 //
    254 class TIntermBranch : public TIntermNode
    255 {
    256  public:
    257    TIntermBranch(TOperator op, TIntermTyped *e) : mFlowOp(op), mExpression(e) {}
    258 
    259    TIntermBranch *getAsBranchNode() override { return this; }
    260    bool visit(Visit visit, TIntermTraverser *it) final;
    261 
    262    size_t getChildCount() const final;
    263    TIntermNode *getChildNode(size_t index) const final;
    264    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    265 
    266    TOperator getFlowOp() { return mFlowOp; }
    267    TIntermTyped *getExpression() { return mExpression; }
    268 
    269    virtual TIntermBranch *deepCopy() const override { return new TIntermBranch(*this); }
    270 
    271  protected:
    272    TOperator mFlowOp;
    273    TIntermTyped *mExpression;  // zero except for "return exp;" statements
    274 
    275  private:
    276    TIntermBranch(const TIntermBranch &);
    277 };
    278 
    279 // Nodes that correspond to variable symbols in the source code. These may be regular variables or
    280 // interface block instances. In declarations that only declare a struct type but no variables, a
    281 // TIntermSymbol node with an empty variable is used to store the type.
    282 class TIntermSymbol : public TIntermTyped
    283 {
    284  public:
    285    TIntermSymbol(const TVariable *variable);
    286 
    287    TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); }
    288 
    289    bool hasConstantValue() const override;
    290    const TConstantUnion *getConstantValue() const override;
    291 
    292    bool hasSideEffects() const override { return false; }
    293 
    294    const TType &getType() const override;
    295 
    296    const TSymbolUniqueId &uniqueId() const;
    297    ImmutableString getName() const;
    298    const TVariable &variable() const { return *mVariable; }
    299 
    300    TIntermSymbol *getAsSymbolNode() override { return this; }
    301    void traverse(TIntermTraverser *it) final;
    302    bool visit(Visit visit, TIntermTraverser *it) final;
    303 
    304    size_t getChildCount() const final;
    305    TIntermNode *getChildNode(size_t index) const final;
    306    bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
    307 
    308  private:
    309    TIntermSymbol(const TIntermSymbol &) = default;  // Note: not deleted, just private!
    310    void propagatePrecision(TPrecision precision) override;
    311 
    312    const TVariable *const mVariable;  // Guaranteed to be non-null
    313 };
    314 
    315 // A typed expression that is not just representing a symbol table symbol.
    316 class TIntermExpression : public TIntermTyped
    317 {
    318  public:
    319    TIntermExpression(const TType &t);
    320 
    321    const TType &getType() const override { return mType; }
    322 
    323  protected:
    324    TType *getTypePointer() { return &mType; }
    325    void setType(const TType &t) { mType = t; }
    326 
    327    TIntermExpression(const TIntermExpression &node) = default;
    328 
    329    TType mType;
    330 };
    331 
    332 // Constant folded node.
    333 // Note that nodes may be constant folded and not be constant expressions with the EvqConst
    334 // qualifier. This happens for example when the following expression is processed:
    335 // "true ? 1.0 : non_constant"
    336 // Other nodes than TIntermConstantUnion may also be constant expressions.
    337 //
    338 class TIntermConstantUnion : public TIntermExpression
    339 {
    340  public:
    341    TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
    342        : TIntermExpression(type), mUnionArrayPointer(unionPointer)
    343    {
    344        ASSERT(unionPointer);
    345    }
    346 
    347    TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
    348 
    349    bool hasConstantValue() const override;
    350    bool isConstantNullValue() const override;
    351    const TConstantUnion *getConstantValue() const override;
    352 
    353    bool hasSideEffects() const override { return false; }
    354 
    355    int getIConst(size_t index) const
    356    {
    357        return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
    358    }
    359    unsigned int getUConst(size_t index) const
    360    {
    361        return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
    362    }
    363    float getFConst(size_t index) const
    364    {
    365        return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
    366    }
    367    bool getBConst(size_t index) const
    368    {
    369        return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
    370    }
    371    bool isZero(size_t index) const
    372    {
    373        return mUnionArrayPointer ? mUnionArrayPointer[index].isZero() : false;
    374    }
    375 
    376    TIntermConstantUnion *getAsConstantUnion() override { return this; }
    377    void traverse(TIntermTraverser *it) final;
    378    bool visit(Visit visit, TIntermTraverser *it) final;
    379 
    380    size_t getChildCount() const final;
    381    TIntermNode *getChildNode(size_t index) const final;
    382    bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
    383 
    384    TConstantUnion *foldUnaryNonComponentWise(TOperator op);
    385    TConstantUnion *foldUnaryComponentWise(TOperator op,
    386                                           const TFunction *function,
    387                                           TDiagnostics *diagnostics);
    388 
    389    static const TConstantUnion *FoldBinary(TOperator op,
    390                                            const TConstantUnion *leftArray,
    391                                            const TType &leftType,
    392                                            const TConstantUnion *rightArray,
    393                                            const TType &rightType,
    394                                            TDiagnostics *diagnostics,
    395                                            const TSourceLoc &line);
    396 
    397    static const TConstantUnion *FoldIndexing(const TType &type,
    398                                              const TConstantUnion *constArray,
    399                                              int index);
    400    static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
    401                                                TDiagnostics *diagnostics);
    402    static bool IsFloatDivision(TBasicType t1, TBasicType t2);
    403 
    404  protected:
    405    // Same data may be shared between multiple constant unions, so it can't be modified.
    406    const TConstantUnion *mUnionArrayPointer;
    407 
    408  private:
    409    typedef float (*FloatTypeUnaryFunc)(float);
    410    void foldFloatTypeUnary(const TConstantUnion &parameter,
    411                            FloatTypeUnaryFunc builtinFunc,
    412                            TConstantUnion *result) const;
    413    void propagatePrecision(TPrecision precision) override;
    414 
    415    TIntermConstantUnion(const TIntermConstantUnion &node);  // Note: not deleted, just private!
    416 };
    417 
    418 //
    419 // Intermediate class for node types that hold operators.
    420 //
    421 class TIntermOperator : public TIntermExpression
    422 {
    423  public:
    424    TOperator getOp() const { return mOp; }
    425 
    426    bool isAssignment() const;
    427    bool isMultiplication() const;
    428    bool isConstructor() const;
    429 
    430    // Returns true for calls mapped to EOpCall*, false for all built-ins.
    431    bool isFunctionCall() const;
    432 
    433    bool hasSideEffects() const override { return isAssignment(); }
    434 
    435  protected:
    436    TIntermOperator(TOperator op) : TIntermExpression(TType(EbtFloat, EbpUndefined)), mOp(op) {}
    437    TIntermOperator(TOperator op, const TType &type) : TIntermExpression(type), mOp(op) {}
    438 
    439    TIntermOperator(const TIntermOperator &) = default;
    440 
    441    const TOperator mOp;
    442 };
    443 
    444 // Node for vector swizzles.
    445 class TIntermSwizzle : public TIntermExpression
    446 {
    447  public:
    448    // This constructor determines the type of the node based on the operand.
    449    TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
    450 
    451    TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
    452 
    453    TIntermSwizzle *getAsSwizzleNode() override { return this; }
    454    bool visit(Visit visit, TIntermTraverser *it) final;
    455 
    456    size_t getChildCount() const final;
    457    TIntermNode *getChildNode(size_t index) const final;
    458    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    459 
    460    bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
    461 
    462    TIntermTyped *getOperand() { return mOperand; }
    463    void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
    464 
    465    const TVector<int> &getSwizzleOffsets() { return mSwizzleOffsets; }
    466 
    467    bool hasDuplicateOffsets() const;
    468    void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
    469    bool offsetsMatch(int offset) const;
    470 
    471    TIntermTyped *fold(TDiagnostics *diagnostics) override;
    472 
    473  protected:
    474    TIntermTyped *mOperand;
    475    TVector<int> mSwizzleOffsets;
    476    bool mHasFoldedDuplicateOffsets;
    477 
    478  private:
    479    void promote();
    480    TPrecision derivePrecision() const override;
    481    void propagatePrecision(TPrecision precision) override;
    482 
    483    TIntermSwizzle(const TIntermSwizzle &node);  // Note: not deleted, just private!
    484 };
    485 
    486 //
    487 // Nodes for all the basic binary math operators.
    488 //
    489 class TIntermBinary : public TIntermOperator
    490 {
    491  public:
    492    // This constructor determines the type of the binary node based on the operands and op.
    493    TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
    494    // Comma qualifier depends on the shader version, so use this to create comma nodes:
    495    static TIntermBinary *CreateComma(TIntermTyped *left, TIntermTyped *right, int shaderVersion);
    496 
    497    TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
    498 
    499    bool hasConstantValue() const override;
    500    const TConstantUnion *getConstantValue() const override;
    501 
    502    static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
    503    static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
    504 
    505    TIntermBinary *getAsBinaryNode() override { return this; }
    506    void traverse(TIntermTraverser *it) final;
    507    bool visit(Visit visit, TIntermTraverser *it) final;
    508 
    509    size_t getChildCount() const final;
    510    TIntermNode *getChildNode(size_t index) const final;
    511    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    512 
    513    bool hasSideEffects() const override
    514    {
    515        return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
    516    }
    517 
    518    TIntermTyped *getLeft() const { return mLeft; }
    519    TIntermTyped *getRight() const { return mRight; }
    520    TIntermTyped *fold(TDiagnostics *diagnostics) override;
    521 
    522    // This method is only valid for EOpIndexDirectStruct. It returns the name of the field.
    523    const ImmutableString &getIndexStructFieldName() const;
    524 
    525  protected:
    526    TIntermTyped *mLeft;
    527    TIntermTyped *mRight;
    528 
    529  private:
    530    void promote();
    531    TPrecision derivePrecision() const override;
    532    void propagatePrecision(TPrecision precision) override;
    533 
    534    static TQualifier GetCommaQualifier(int shaderVersion,
    535                                        const TIntermTyped *left,
    536                                        const TIntermTyped *right);
    537 
    538    TIntermBinary(const TIntermBinary &node);  // Note: not deleted, just private!
    539 };
    540 
    541 //
    542 // Nodes for unary math operators.
    543 //
    544 class TIntermUnary : public TIntermOperator
    545 {
    546  public:
    547    TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
    548 
    549    TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
    550 
    551    TIntermUnary *getAsUnaryNode() override { return this; }
    552    void traverse(TIntermTraverser *it) final;
    553    bool visit(Visit visit, TIntermTraverser *it) final;
    554 
    555    size_t getChildCount() const final;
    556    TIntermNode *getChildNode(size_t index) const final;
    557    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    558 
    559    bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
    560 
    561    TIntermTyped *getOperand() { return mOperand; }
    562    TIntermTyped *fold(TDiagnostics *diagnostics) override;
    563 
    564    const TFunction *getFunction() const { return mFunction; }
    565 
    566    void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
    567    bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
    568 
    569  protected:
    570    TIntermTyped *mOperand;
    571 
    572    // If set to true, replace the built-in function call with an emulated one
    573    // to work around driver bugs.
    574    bool mUseEmulatedFunction;
    575 
    576    const TFunction *const mFunction;
    577 
    578  private:
    579    void promote();
    580    TPrecision derivePrecision() const override;
    581    void propagatePrecision(TPrecision precision) override;
    582 
    583    TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
    584 };
    585 
    586 typedef TVector<TIntermNode *> TIntermSequence;
    587 typedef TVector<int> TQualifierList;
    588 
    589 // Interface for node classes that have an arbitrarily sized set of children.
    590 class TIntermAggregateBase
    591 {
    592  public:
    593    virtual ~TIntermAggregateBase() {}
    594 
    595    virtual TIntermSequence *getSequence()             = 0;
    596    virtual const TIntermSequence *getSequence() const = 0;
    597 
    598    bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
    599    bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
    600 
    601  protected:
    602    TIntermAggregateBase() {}
    603 
    604    bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
    605 };
    606 
    607 //
    608 // Nodes that operate on an arbitrary sized set of children.
    609 //
    610 class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
    611 {
    612  public:
    613    static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
    614 
    615    static TIntermAggregate *CreateRawFunctionCall(const TFunction &func,
    616                                                   TIntermSequence *arguments);
    617 
    618    // This covers all built-in function calls.
    619    static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
    620                                                       TIntermSequence *arguments);
    621    static TIntermAggregate *CreateConstructor(const TType &type, TIntermSequence *arguments);
    622    static TIntermAggregate *CreateConstructor(
    623        const TType &type,
    624        const std::initializer_list<TIntermNode *> &arguments);
    625    ~TIntermAggregate() override {}
    626 
    627    // Note: only supported for nodes that can be a part of an expression.
    628    TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
    629 
    630    TIntermAggregate *shallowCopy() const;
    631 
    632    bool hasConstantValue() const override;
    633    bool isConstantNullValue() const override;
    634    const TConstantUnion *getConstantValue() const override;
    635 
    636    TIntermAggregate *getAsAggregate() override { return this; }
    637    void traverse(TIntermTraverser *it) final;
    638    bool visit(Visit visit, TIntermTraverser *it) final;
    639 
    640    size_t getChildCount() const final;
    641    TIntermNode *getChildNode(size_t index) const final;
    642    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    643 
    644    bool hasSideEffects() const override;
    645 
    646    TIntermTyped *fold(TDiagnostics *diagnostics) override;
    647 
    648    TIntermSequence *getSequence() override { return &mArguments; }
    649    const TIntermSequence *getSequence() const override { return &mArguments; }
    650 
    651    void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
    652    bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
    653 
    654    const TFunction *getFunction() const { return mFunction; }
    655 
    656    // Get the function name to display to the user in an error message.
    657    const char *functionName() const;
    658 
    659  protected:
    660    TIntermSequence mArguments;
    661 
    662    // If set to true, replace the built-in function call with an emulated one
    663    // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
    664    bool mUseEmulatedFunction;
    665 
    666    const TFunction *const mFunction;
    667 
    668  private:
    669    TIntermAggregate(const TFunction *func,
    670                     const TType &type,
    671                     TOperator op,
    672                     TIntermSequence *arguments);
    673 
    674    TIntermAggregate(const TIntermAggregate &node);  // note: not deleted, just private!
    675 
    676    void setPrecisionAndQualifier();
    677    TPrecision derivePrecision() const override;
    678    void propagatePrecision(TPrecision precision) override;
    679 
    680    bool areChildrenConstQualified();
    681 };
    682 
    683 // A list of statements. Either the root node which contains declarations and function definitions,
    684 // or a block that can be marked with curly braces {}.
    685 class TIntermBlock : public TIntermNode, public TIntermAggregateBase
    686 {
    687  public:
    688    TIntermBlock() : TIntermNode(), mIsTreeRoot(false) {}
    689    TIntermBlock(std::initializer_list<TIntermNode *> stmts);
    690    ~TIntermBlock() override {}
    691 
    692    TIntermBlock *getAsBlock() override { return this; }
    693    void traverse(TIntermTraverser *it) final;
    694    bool visit(Visit visit, TIntermTraverser *it) final;
    695 
    696    size_t getChildCount() const final;
    697    TIntermNode *getChildNode(size_t index) const final;
    698    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    699    void replaceAllChildren(const TIntermSequence &newStatements);
    700 
    701    // Only intended for initially building the block.
    702    void appendStatement(TIntermNode *statement);
    703    void insertStatement(size_t insertPosition, TIntermNode *statement);
    704 
    705    TIntermSequence *getSequence() override { return &mStatements; }
    706    const TIntermSequence *getSequence() const override { return &mStatements; }
    707 
    708    TIntermBlock *deepCopy() const override { return new TIntermBlock(*this); }
    709 
    710    void setIsTreeRoot() { mIsTreeRoot = true; }
    711    bool isTreeRoot() const { return mIsTreeRoot; }
    712 
    713  protected:
    714    TIntermSequence mStatements;
    715 
    716    // Used to distinguish the tree root from the other blocks.  When validating the AST, some
    717    // validations are not applicable if not run on the entire tree and are thus skipped.
    718    bool mIsTreeRoot;
    719 
    720  private:
    721    TIntermBlock(const TIntermBlock &);
    722 };
    723 
    724 // Function prototype. May be in the AST either as a function prototype declaration or as a part of
    725 // a function definition. The type of the node is the function return type.
    726 class TIntermFunctionPrototype : public TIntermTyped
    727 {
    728  public:
    729    TIntermFunctionPrototype(const TFunction *function);
    730    ~TIntermFunctionPrototype() override {}
    731 
    732    TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
    733    void traverse(TIntermTraverser *it) final;
    734    bool visit(Visit visit, TIntermTraverser *it) final;
    735 
    736    size_t getChildCount() const final;
    737    TIntermNode *getChildNode(size_t index) const final;
    738    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    739 
    740    const TType &getType() const override;
    741 
    742    TIntermTyped *deepCopy() const override
    743    {
    744        UNREACHABLE();
    745        return nullptr;
    746    }
    747    bool hasSideEffects() const override
    748    {
    749        UNREACHABLE();
    750        return true;
    751    }
    752 
    753    const TFunction *getFunction() const { return mFunction; }
    754 
    755  protected:
    756    const TFunction *const mFunction;
    757 };
    758 
    759 // Node for function definitions. The prototype child node stores the function header including
    760 // parameters, and the body child node stores the function body.
    761 class TIntermFunctionDefinition : public TIntermNode
    762 {
    763  public:
    764    TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
    765        : TIntermNode(), mPrototype(prototype), mBody(body)
    766    {
    767        ASSERT(prototype != nullptr);
    768        ASSERT(body != nullptr);
    769    }
    770 
    771    TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
    772    void traverse(TIntermTraverser *it) final;
    773    bool visit(Visit visit, TIntermTraverser *it) final;
    774 
    775    size_t getChildCount() const final;
    776    TIntermNode *getChildNode(size_t index) const final;
    777    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    778 
    779    TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
    780    TIntermBlock *getBody() const { return mBody; }
    781 
    782    const TFunction *getFunction() const { return mPrototype->getFunction(); }
    783 
    784    TIntermNode *deepCopy() const override
    785    {
    786        UNREACHABLE();
    787        return nullptr;
    788    }
    789 
    790  private:
    791    TIntermFunctionPrototype *mPrototype;
    792    TIntermBlock *mBody;
    793 };
    794 
    795 // Struct, interface block or variable declaration. Can contain multiple variable declarators.
    796 class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
    797 {
    798  public:
    799    TIntermDeclaration() : TIntermNode() {}
    800    TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr);
    801    TIntermDeclaration(std::initializer_list<const TVariable *> declarators);
    802    TIntermDeclaration(std::initializer_list<TIntermTyped *> declarators);
    803    ~TIntermDeclaration() override {}
    804 
    805    TIntermDeclaration *getAsDeclarationNode() override { return this; }
    806    bool visit(Visit visit, TIntermTraverser *it) final;
    807 
    808    size_t getChildCount() const final;
    809    TIntermNode *getChildNode(size_t index) const final;
    810    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    811 
    812    // Only intended for initially building the declaration.
    813    // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
    814    // EOpInitialize.
    815    void appendDeclarator(TIntermTyped *declarator);
    816 
    817    TIntermSequence *getSequence() override { return &mDeclarators; }
    818    const TIntermSequence *getSequence() const override { return &mDeclarators; }
    819 
    820    TIntermDeclaration *deepCopy() const override
    821    {
    822        // Note: This is only useful as support for deepCopy of TIntermBlock and TIntermLoop, but is
    823        // not sufficient as it will be redeclaring the same TVariable.  If a function body is
    824        // duplicated for example, it means that both functions reference the same TVariable pointer
    825        // which works, but is technically not correct.  In particular, maps with TVariable * as key
    826        // can get confused.
    827        //
    828        // After deepCopy() is issued, ReplaceVariables must be used to replace every declared
    829        // variable with a duplicate.  This is NOT automatically done when deepCopy-ing TIntermBlock
    830        // and TIntermLoop nodes.
    831        return new TIntermDeclaration(*this);
    832    }
    833 
    834  protected:
    835    TIntermDeclaration(const TIntermDeclaration &node);
    836 
    837    TIntermSequence mDeclarators;
    838 };
    839 
    840 // Specialized declarations for attributing invariance.
    841 class TIntermGlobalQualifierDeclaration : public TIntermNode
    842 {
    843  public:
    844    TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol,
    845                                      bool isPrecise,
    846                                      const TSourceLoc &line);
    847 
    848    virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override
    849    {
    850        return this;
    851    }
    852    bool visit(Visit visit, TIntermTraverser *it) final;
    853 
    854    TIntermSymbol *getSymbol() { return mSymbol; }
    855    bool isInvariant() const { return !mIsPrecise; }
    856    bool isPrecise() const { return mIsPrecise; }
    857 
    858    size_t getChildCount() const final;
    859    TIntermNode *getChildNode(size_t index) const final;
    860    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    861 
    862    TIntermGlobalQualifierDeclaration *deepCopy() const override
    863    {
    864        return new TIntermGlobalQualifierDeclaration(*this);
    865    }
    866 
    867  private:
    868    TIntermSymbol *mSymbol;
    869    // Either |precise| or |invariant|, determined based on this flag.
    870    bool mIsPrecise;
    871 
    872    TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &);
    873 };
    874 
    875 // For ternary operators like a ? b : c.
    876 class TIntermTernary : public TIntermExpression
    877 {
    878  public:
    879    TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
    880 
    881    TIntermTernary *getAsTernaryNode() override { return this; }
    882    bool visit(Visit visit, TIntermTraverser *it) final;
    883 
    884    size_t getChildCount() const final;
    885    TIntermNode *getChildNode(size_t index) const final;
    886    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    887 
    888    TIntermTyped *getCondition() const { return mCondition; }
    889    TIntermTyped *getTrueExpression() const { return mTrueExpression; }
    890    TIntermTyped *getFalseExpression() const { return mFalseExpression; }
    891 
    892    TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
    893 
    894    bool hasSideEffects() const override
    895    {
    896        return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
    897               mFalseExpression->hasSideEffects();
    898    }
    899 
    900    TIntermTyped *fold(TDiagnostics *diagnostics) override;
    901 
    902  private:
    903    TIntermTernary(const TIntermTernary &node);  // Note: not deleted, just private!
    904 
    905    static TQualifier DetermineQualifier(TIntermTyped *cond,
    906                                         TIntermTyped *trueExpression,
    907                                         TIntermTyped *falseExpression);
    908    TPrecision derivePrecision() const override;
    909    void propagatePrecision(TPrecision precision) override;
    910 
    911    TIntermTyped *mCondition;
    912    TIntermTyped *mTrueExpression;
    913    TIntermTyped *mFalseExpression;
    914 };
    915 
    916 class TIntermIfElse : public TIntermNode
    917 {
    918  public:
    919    TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
    920 
    921    TIntermIfElse *getAsIfElseNode() override { return this; }
    922    bool visit(Visit visit, TIntermTraverser *it) final;
    923 
    924    size_t getChildCount() const final;
    925    TIntermNode *getChildNode(size_t index) const final;
    926    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    927 
    928    TIntermTyped *getCondition() const { return mCondition; }
    929    TIntermBlock *getTrueBlock() const { return mTrueBlock; }
    930    TIntermBlock *getFalseBlock() const { return mFalseBlock; }
    931 
    932    TIntermIfElse *deepCopy() const override { return new TIntermIfElse(*this); }
    933 
    934  protected:
    935    TIntermTyped *mCondition;
    936    TIntermBlock *mTrueBlock;
    937    TIntermBlock *mFalseBlock;
    938 
    939  private:
    940    TIntermIfElse(const TIntermIfElse &);
    941 };
    942 
    943 //
    944 // Switch statement.
    945 //
    946 class TIntermSwitch : public TIntermNode
    947 {
    948  public:
    949    TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
    950 
    951    TIntermSwitch *getAsSwitchNode() override { return this; }
    952    bool visit(Visit visit, TIntermTraverser *it) final;
    953 
    954    size_t getChildCount() const final;
    955    TIntermNode *getChildNode(size_t index) const final;
    956    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    957 
    958    TIntermTyped *getInit() { return mInit; }
    959    TIntermBlock *getStatementList() { return mStatementList; }
    960 
    961    // Must be called with a non-null statementList.
    962    void setStatementList(TIntermBlock *statementList);
    963 
    964    TIntermSwitch *deepCopy() const override { return new TIntermSwitch(*this); }
    965 
    966  protected:
    967    TIntermTyped *mInit;
    968    TIntermBlock *mStatementList;
    969 
    970  private:
    971    TIntermSwitch(const TIntermSwitch &);
    972 };
    973 
    974 //
    975 // Case label.
    976 //
    977 class TIntermCase : public TIntermNode
    978 {
    979  public:
    980    TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
    981 
    982    TIntermCase *getAsCaseNode() override { return this; }
    983    bool visit(Visit visit, TIntermTraverser *it) final;
    984 
    985    size_t getChildCount() const final;
    986    TIntermNode *getChildNode(size_t index) const final;
    987    bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
    988 
    989    bool hasCondition() const { return mCondition != nullptr; }
    990    TIntermTyped *getCondition() const { return mCondition; }
    991 
    992    TIntermCase *deepCopy() const override { return new TIntermCase(*this); }
    993 
    994  protected:
    995    TIntermTyped *mCondition;
    996 
    997  private:
    998    TIntermCase(const TIntermCase &);
    999 };
   1000 
   1001 //
   1002 // Preprocessor Directive.
   1003 //  #ifdef, #define, #if, #endif, etc.
   1004 //
   1005 
   1006 enum class PreprocessorDirective
   1007 {
   1008    Define,
   1009    Ifdef,
   1010    If,
   1011    Endif,
   1012 };
   1013 
   1014 class TIntermPreprocessorDirective final : public TIntermNode
   1015 {
   1016  public:
   1017    // This could also take an ImmutableString as an argument.
   1018    TIntermPreprocessorDirective(PreprocessorDirective directive, ImmutableString command);
   1019    ~TIntermPreprocessorDirective() final;
   1020 
   1021    void traverse(TIntermTraverser *it) final;
   1022    bool visit(Visit visit, TIntermTraverser *it) final;
   1023    bool replaceChildNode(TIntermNode *, TIntermNode *) final { return false; }
   1024 
   1025    TIntermPreprocessorDirective *getAsPreprocessorDirective() final { return this; }
   1026    size_t getChildCount() const final;
   1027    TIntermNode *getChildNode(size_t index) const final;
   1028 
   1029    PreprocessorDirective getDirective() const { return mDirective; }
   1030    const ImmutableString &getCommand() const { return mCommand; }
   1031 
   1032    TIntermPreprocessorDirective *deepCopy() const override
   1033    {
   1034        return new TIntermPreprocessorDirective(*this);
   1035    }
   1036 
   1037  private:
   1038    PreprocessorDirective mDirective;
   1039    ImmutableString mCommand;
   1040 
   1041    TIntermPreprocessorDirective(const TIntermPreprocessorDirective &);
   1042 };
   1043 
   1044 }  // namespace sh
   1045 
   1046 #endif  // COMPILER_TRANSLATOR_INTERMNODE_H_