• 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 
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     ImmutableString getOffsetsAsXYZW() const;
467     void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
468 
getSwizzleOffsets()469     const TVector<int> &getSwizzleOffsets() { return mSwizzleOffsets; }
470 
471     bool hasDuplicateOffsets() const;
472     void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
473     bool offsetsMatch(int offset) const;
474 
475     TIntermTyped *fold(TDiagnostics *diagnostics) override;
476 
477   protected:
478     TIntermTyped *mOperand;
479     TVector<int> mSwizzleOffsets;
480     bool mHasFoldedDuplicateOffsets;
481 
482   private:
483     void promote();
484     TPrecision derivePrecision() const override;
485     void propagatePrecision(TPrecision precision) override;
486 
487     TIntermSwizzle(const TIntermSwizzle &node);  // Note: not deleted, just private!
488 };
489 
490 //
491 // Nodes for all the basic binary math operators.
492 //
493 class TIntermBinary : public TIntermOperator
494 {
495   public:
496     // This constructor determines the type of the binary node based on the operands and op.
497     TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
498     // Comma qualifier depends on the shader version, so use this to create comma nodes:
499     static TIntermBinary *CreateComma(TIntermTyped *left, TIntermTyped *right, int shaderVersion);
500 
deepCopy()501     TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
502 
503     bool hasConstantValue() const override;
504     const TConstantUnion *getConstantValue() const override;
505 
506     static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
507     static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
508 
getAsBinaryNode()509     TIntermBinary *getAsBinaryNode() override { return this; }
510     void traverse(TIntermTraverser *it) final;
511     bool visit(Visit visit, TIntermTraverser *it) final;
512 
513     size_t getChildCount() const final;
514     TIntermNode *getChildNode(size_t index) const final;
515     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
516 
hasSideEffects()517     bool hasSideEffects() const override
518     {
519         return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
520     }
521 
getLeft()522     TIntermTyped *getLeft() const { return mLeft; }
getRight()523     TIntermTyped *getRight() const { return mRight; }
524     TIntermTyped *fold(TDiagnostics *diagnostics) override;
525 
526     // This method is only valid for EOpIndexDirectStruct. It returns the name of the field.
527     const ImmutableString &getIndexStructFieldName() const;
528 
529   protected:
530     TIntermTyped *mLeft;
531     TIntermTyped *mRight;
532 
533   private:
534     void promote();
535     TPrecision derivePrecision() const override;
536     void propagatePrecision(TPrecision precision) override;
537 
538     static TQualifier GetCommaQualifier(int shaderVersion,
539                                         const TIntermTyped *left,
540                                         const TIntermTyped *right);
541 
542     TIntermBinary(const TIntermBinary &node);  // Note: not deleted, just private!
543 };
544 
545 //
546 // Nodes for unary math operators.
547 //
548 class TIntermUnary : public TIntermOperator
549 {
550   public:
551     TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
552 
deepCopy()553     TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
554 
getAsUnaryNode()555     TIntermUnary *getAsUnaryNode() override { return this; }
556     void traverse(TIntermTraverser *it) final;
557     bool visit(Visit visit, TIntermTraverser *it) final;
558 
559     size_t getChildCount() const final;
560     TIntermNode *getChildNode(size_t index) const final;
561     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
562 
hasSideEffects()563     bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
564 
getOperand()565     TIntermTyped *getOperand() { return mOperand; }
566     TIntermTyped *fold(TDiagnostics *diagnostics) override;
567 
getFunction()568     const TFunction *getFunction() const { return mFunction; }
569 
setUseEmulatedFunction()570     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
getUseEmulatedFunction()571     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
572 
573   protected:
574     TIntermTyped *mOperand;
575 
576     // If set to true, replace the built-in function call with an emulated one
577     // to work around driver bugs.
578     bool mUseEmulatedFunction;
579 
580     const TFunction *const mFunction;
581 
582   private:
583     void promote();
584     TPrecision derivePrecision() const override;
585     void propagatePrecision(TPrecision precision) override;
586 
587     TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
588 };
589 
590 typedef TVector<TIntermNode *> TIntermSequence;
591 typedef TVector<int> TQualifierList;
592 
593 // Interface for node classes that have an arbitrarily sized set of children.
594 class TIntermAggregateBase
595 {
596   public:
~TIntermAggregateBase()597     virtual ~TIntermAggregateBase() {}
598 
599     virtual TIntermSequence *getSequence()             = 0;
600     virtual const TIntermSequence *getSequence() const = 0;
601 
602     bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
603     bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
604 
605   protected:
TIntermAggregateBase()606     TIntermAggregateBase() {}
607 
608     bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
609 };
610 
611 //
612 // Nodes that operate on an arbitrary sized set of children.
613 //
614 class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
615 {
616   public:
617     static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
618 
619     static TIntermAggregate *CreateRawFunctionCall(const TFunction &func,
620                                                    TIntermSequence *arguments);
621 
622     // This covers all built-in function calls.
623     static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
624                                                        TIntermSequence *arguments);
625     static TIntermAggregate *CreateConstructor(const TType &type, TIntermSequence *arguments);
626     static TIntermAggregate *CreateConstructor(
627         const TType &type,
628         const std::initializer_list<TIntermNode *> &arguments);
~TIntermAggregate()629     ~TIntermAggregate() override {}
630 
631     // Note: only supported for nodes that can be a part of an expression.
deepCopy()632     TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
633 
634     TIntermAggregate *shallowCopy() const;
635 
636     bool hasConstantValue() const override;
637     bool isConstantNullValue() const override;
638     const TConstantUnion *getConstantValue() const override;
639 
getAsAggregate()640     TIntermAggregate *getAsAggregate() override { return this; }
641     void traverse(TIntermTraverser *it) final;
642     bool visit(Visit visit, TIntermTraverser *it) final;
643 
644     size_t getChildCount() const final;
645     TIntermNode *getChildNode(size_t index) const final;
646     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
647 
648     bool hasSideEffects() const override;
649 
650     TIntermTyped *fold(TDiagnostics *diagnostics) override;
651 
getSequence()652     TIntermSequence *getSequence() override { return &mArguments; }
getSequence()653     const TIntermSequence *getSequence() const override { return &mArguments; }
654 
setUseEmulatedFunction()655     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
getUseEmulatedFunction()656     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
657 
getFunction()658     const TFunction *getFunction() const { return mFunction; }
659 
660     // Get the function name to display to the user in an error message.
661     const char *functionName() const;
662 
663   protected:
664     TIntermSequence mArguments;
665 
666     // If set to true, replace the built-in function call with an emulated one
667     // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
668     bool mUseEmulatedFunction;
669 
670     const TFunction *const mFunction;
671 
672   private:
673     TIntermAggregate(const TFunction *func,
674                      const TType &type,
675                      TOperator op,
676                      TIntermSequence *arguments);
677 
678     TIntermAggregate(const TIntermAggregate &node);  // note: not deleted, just private!
679 
680     void setPrecisionAndQualifier();
681     TPrecision derivePrecision() const override;
682     void propagatePrecision(TPrecision precision) override;
683 
684     bool areChildrenConstQualified();
685 };
686 
687 // A list of statements. Either the root node which contains declarations and function definitions,
688 // or a block that can be marked with curly braces {}.
689 class TIntermBlock : public TIntermNode, public TIntermAggregateBase
690 {
691   public:
TIntermBlock()692     TIntermBlock() : TIntermNode(), mIsTreeRoot(false) {}
693     TIntermBlock(std::initializer_list<TIntermNode *> stmts);
~TIntermBlock()694     ~TIntermBlock() override {}
695 
getAsBlock()696     TIntermBlock *getAsBlock() override { return this; }
697     void traverse(TIntermTraverser *it) final;
698     bool visit(Visit visit, TIntermTraverser *it) final;
699 
700     size_t getChildCount() const final;
701     TIntermNode *getChildNode(size_t index) const final;
702     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
703     void replaceAllChildren(const TIntermSequence &newStatements);
704 
705     // Only intended for initially building the block.
706     void appendStatement(TIntermNode *statement);
707     void insertStatement(size_t insertPosition, TIntermNode *statement);
708 
getSequence()709     TIntermSequence *getSequence() override { return &mStatements; }
getSequence()710     const TIntermSequence *getSequence() const override { return &mStatements; }
711 
deepCopy()712     TIntermBlock *deepCopy() const override { return new TIntermBlock(*this); }
713 
setIsTreeRoot()714     void setIsTreeRoot() { mIsTreeRoot = true; }
isTreeRoot()715     bool isTreeRoot() const { return mIsTreeRoot; }
716 
717   protected:
718     TIntermSequence mStatements;
719 
720     // Used to distinguish the tree root from the other blocks.  When validating the AST, some
721     // validations are not applicable if not run on the entire tree and are thus skipped.
722     bool mIsTreeRoot;
723 
724   private:
725     TIntermBlock(const TIntermBlock &);
726 };
727 
728 // Function prototype. May be in the AST either as a function prototype declaration or as a part of
729 // a function definition. The type of the node is the function return type.
730 class TIntermFunctionPrototype : public TIntermTyped
731 {
732   public:
733     TIntermFunctionPrototype(const TFunction *function);
~TIntermFunctionPrototype()734     ~TIntermFunctionPrototype() override {}
735 
getAsFunctionPrototypeNode()736     TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
737     void traverse(TIntermTraverser *it) final;
738     bool visit(Visit visit, TIntermTraverser *it) final;
739 
740     size_t getChildCount() const final;
741     TIntermNode *getChildNode(size_t index) const final;
742     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
743 
744     const TType &getType() const override;
745 
deepCopy()746     TIntermTyped *deepCopy() const override
747     {
748         UNREACHABLE();
749         return nullptr;
750     }
hasSideEffects()751     bool hasSideEffects() const override
752     {
753         UNREACHABLE();
754         return true;
755     }
756 
getFunction()757     const TFunction *getFunction() const { return mFunction; }
758 
759   protected:
760     const TFunction *const mFunction;
761 };
762 
763 // Node for function definitions. The prototype child node stores the function header including
764 // parameters, and the body child node stores the function body.
765 class TIntermFunctionDefinition : public TIntermNode
766 {
767   public:
TIntermFunctionDefinition(TIntermFunctionPrototype * prototype,TIntermBlock * body)768     TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
769         : TIntermNode(), mPrototype(prototype), mBody(body)
770     {
771         ASSERT(prototype != nullptr);
772         ASSERT(body != nullptr);
773     }
774 
getAsFunctionDefinition()775     TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
776     void traverse(TIntermTraverser *it) final;
777     bool visit(Visit visit, TIntermTraverser *it) final;
778 
779     size_t getChildCount() const final;
780     TIntermNode *getChildNode(size_t index) const final;
781     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
782 
getFunctionPrototype()783     TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
getBody()784     TIntermBlock *getBody() const { return mBody; }
785 
getFunction()786     const TFunction *getFunction() const { return mPrototype->getFunction(); }
787 
deepCopy()788     TIntermNode *deepCopy() const override
789     {
790         UNREACHABLE();
791         return nullptr;
792     }
793 
794   private:
795     TIntermFunctionPrototype *mPrototype;
796     TIntermBlock *mBody;
797 };
798 
799 // Struct, interface block or variable declaration. Can contain multiple variable declarators.
800 class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
801 {
802   public:
TIntermDeclaration()803     TIntermDeclaration() : TIntermNode() {}
804     TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr);
805     TIntermDeclaration(std::initializer_list<const TVariable *> declarators);
806     TIntermDeclaration(std::initializer_list<TIntermTyped *> declarators);
~TIntermDeclaration()807     ~TIntermDeclaration() override {}
808 
getAsDeclarationNode()809     TIntermDeclaration *getAsDeclarationNode() override { return this; }
810     bool visit(Visit visit, TIntermTraverser *it) final;
811 
812     size_t getChildCount() const final;
813     TIntermNode *getChildNode(size_t index) const final;
814     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
815 
816     // Only intended for initially building the declaration.
817     // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
818     // EOpInitialize.
819     void appendDeclarator(TIntermTyped *declarator);
820 
getSequence()821     TIntermSequence *getSequence() override { return &mDeclarators; }
getSequence()822     const TIntermSequence *getSequence() const override { return &mDeclarators; }
823 
deepCopy()824     TIntermDeclaration *deepCopy() const override
825     {
826         // Note: This is only useful as support for deepCopy of TIntermBlock and TIntermLoop, but is
827         // not sufficient as it will be redeclaring the same TVariable.  If a function body is
828         // duplicated for example, it means that both functions reference the same TVariable pointer
829         // which works, but is technically not correct.  In particular, maps with TVariable * as key
830         // can get confused.
831         //
832         // After deepCopy() is issued, ReplaceVariables must be used to replace every declared
833         // variable with a duplicate.  This is NOT automatically done when deepCopy-ing TIntermBlock
834         // and TIntermLoop nodes.
835         return new TIntermDeclaration(*this);
836     }
837 
838   protected:
839     TIntermDeclaration(const TIntermDeclaration &node);
840 
841     TIntermSequence mDeclarators;
842 };
843 
844 // Specialized declarations for attributing invariance.
845 class TIntermGlobalQualifierDeclaration : public TIntermNode
846 {
847   public:
848     TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol,
849                                       bool isPrecise,
850                                       const TSourceLoc &line);
851 
getAsGlobalQualifierDeclarationNode()852     virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override
853     {
854         return this;
855     }
856     bool visit(Visit visit, TIntermTraverser *it) final;
857 
getSymbol()858     TIntermSymbol *getSymbol() { return mSymbol; }
isInvariant()859     bool isInvariant() const { return !mIsPrecise; }
isPrecise()860     bool isPrecise() const { return mIsPrecise; }
861 
862     size_t getChildCount() const final;
863     TIntermNode *getChildNode(size_t index) const final;
864     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
865 
deepCopy()866     TIntermGlobalQualifierDeclaration *deepCopy() const override
867     {
868         return new TIntermGlobalQualifierDeclaration(*this);
869     }
870 
871   private:
872     TIntermSymbol *mSymbol;
873     // Either |precise| or |invariant|, determined based on this flag.
874     bool mIsPrecise;
875 
876     TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &);
877 };
878 
879 // For ternary operators like a ? b : c.
880 class TIntermTernary : public TIntermExpression
881 {
882   public:
883     TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
884 
getAsTernaryNode()885     TIntermTernary *getAsTernaryNode() override { return this; }
886     bool visit(Visit visit, TIntermTraverser *it) final;
887 
888     size_t getChildCount() const final;
889     TIntermNode *getChildNode(size_t index) const final;
890     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
891 
getCondition()892     TIntermTyped *getCondition() const { return mCondition; }
getTrueExpression()893     TIntermTyped *getTrueExpression() const { return mTrueExpression; }
getFalseExpression()894     TIntermTyped *getFalseExpression() const { return mFalseExpression; }
895 
deepCopy()896     TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
897 
hasSideEffects()898     bool hasSideEffects() const override
899     {
900         return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
901                mFalseExpression->hasSideEffects();
902     }
903 
904     TIntermTyped *fold(TDiagnostics *diagnostics) override;
905 
906   private:
907     TIntermTernary(const TIntermTernary &node);  // Note: not deleted, just private!
908 
909     static TQualifier DetermineQualifier(TIntermTyped *cond,
910                                          TIntermTyped *trueExpression,
911                                          TIntermTyped *falseExpression);
912     TPrecision derivePrecision() const override;
913     void propagatePrecision(TPrecision precision) override;
914 
915     TIntermTyped *mCondition;
916     TIntermTyped *mTrueExpression;
917     TIntermTyped *mFalseExpression;
918 };
919 
920 class TIntermIfElse : public TIntermNode
921 {
922   public:
923     TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
924 
getAsIfElseNode()925     TIntermIfElse *getAsIfElseNode() override { return this; }
926     bool visit(Visit visit, TIntermTraverser *it) final;
927 
928     size_t getChildCount() const final;
929     TIntermNode *getChildNode(size_t index) const final;
930     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
931 
getCondition()932     TIntermTyped *getCondition() const { return mCondition; }
getTrueBlock()933     TIntermBlock *getTrueBlock() const { return mTrueBlock; }
getFalseBlock()934     TIntermBlock *getFalseBlock() const { return mFalseBlock; }
935 
deepCopy()936     TIntermIfElse *deepCopy() const override { return new TIntermIfElse(*this); }
937 
938   protected:
939     TIntermTyped *mCondition;
940     TIntermBlock *mTrueBlock;
941     TIntermBlock *mFalseBlock;
942 
943   private:
944     TIntermIfElse(const TIntermIfElse &);
945 };
946 
947 //
948 // Switch statement.
949 //
950 class TIntermSwitch : public TIntermNode
951 {
952   public:
953     TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
954 
getAsSwitchNode()955     TIntermSwitch *getAsSwitchNode() override { return this; }
956     bool visit(Visit visit, TIntermTraverser *it) final;
957 
958     size_t getChildCount() const final;
959     TIntermNode *getChildNode(size_t index) const final;
960     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
961 
getInit()962     TIntermTyped *getInit() { return mInit; }
getStatementList()963     TIntermBlock *getStatementList() { return mStatementList; }
964 
965     // Must be called with a non-null statementList.
966     void setStatementList(TIntermBlock *statementList);
967 
deepCopy()968     TIntermSwitch *deepCopy() const override { return new TIntermSwitch(*this); }
969 
970   protected:
971     TIntermTyped *mInit;
972     TIntermBlock *mStatementList;
973 
974   private:
975     TIntermSwitch(const TIntermSwitch &);
976 };
977 
978 //
979 // Case label.
980 //
981 class TIntermCase : public TIntermNode
982 {
983   public:
TIntermCase(TIntermTyped * condition)984     TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
985 
getAsCaseNode()986     TIntermCase *getAsCaseNode() override { return this; }
987     bool visit(Visit visit, TIntermTraverser *it) final;
988 
989     size_t getChildCount() const final;
990     TIntermNode *getChildNode(size_t index) const final;
991     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
992 
hasCondition()993     bool hasCondition() const { return mCondition != nullptr; }
getCondition()994     TIntermTyped *getCondition() const { return mCondition; }
995 
deepCopy()996     TIntermCase *deepCopy() const override { return new TIntermCase(*this); }
997 
998   protected:
999     TIntermTyped *mCondition;
1000 
1001   private:
1002     TIntermCase(const TIntermCase &);
1003 };
1004 
1005 //
1006 // Preprocessor Directive.
1007 //  #ifdef, #define, #if, #endif, etc.
1008 //
1009 
1010 enum class PreprocessorDirective
1011 {
1012     Define,
1013     Ifdef,
1014     If,
1015     Endif,
1016 };
1017 
1018 class TIntermPreprocessorDirective final : public TIntermNode
1019 {
1020   public:
1021     // This could also take an ImmutableString as an argument.
1022     TIntermPreprocessorDirective(PreprocessorDirective directive, ImmutableString command);
1023     ~TIntermPreprocessorDirective() final;
1024 
1025     void traverse(TIntermTraverser *it) final;
1026     bool visit(Visit visit, TIntermTraverser *it) final;
replaceChildNode(TIntermNode *,TIntermNode *)1027     bool replaceChildNode(TIntermNode *, TIntermNode *) final { return false; }
1028 
getAsPreprocessorDirective()1029     TIntermPreprocessorDirective *getAsPreprocessorDirective() final { return this; }
1030     size_t getChildCount() const final;
1031     TIntermNode *getChildNode(size_t index) const final;
1032 
getDirective()1033     PreprocessorDirective getDirective() const { return mDirective; }
getCommand()1034     const ImmutableString &getCommand() const { return mCommand; }
1035 
deepCopy()1036     TIntermPreprocessorDirective *deepCopy() const override
1037     {
1038         return new TIntermPreprocessorDirective(*this);
1039     }
1040 
1041   private:
1042     PreprocessorDirective mDirective;
1043     ImmutableString mCommand;
1044 
1045     TIntermPreprocessorDirective(const TIntermPreprocessorDirective &);
1046 };
1047 
EnsureBody(TIntermBlock * body)1048 inline TIntermBlock *TIntermLoop::EnsureBody(TIntermBlock *body)
1049 {
1050     if (ANGLE_LIKELY(body))
1051     {
1052         return body;
1053     }
1054     UNREACHABLE();
1055     return new TIntermBlock();
1056 }
1057 
1058 }  // namespace sh
1059 
1060 #endif  // COMPILER_TRANSLATOR_INTERMNODE_H_
1061