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