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