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