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