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