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