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