1 //
2 // Copyright (c) 2002-2014 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/Operator.h"
28 #include "compiler/translator/SymbolUniqueId.h"
29 #include "compiler/translator/Types.h"
30 
31 namespace sh
32 {
33 
34 class TDiagnostics;
35 
36 class TIntermTraverser;
37 class TIntermAggregate;
38 class TIntermBlock;
39 class TIntermInvariantDeclaration;
40 class TIntermDeclaration;
41 class TIntermFunctionPrototype;
42 class TIntermFunctionDefinition;
43 class TIntermSwizzle;
44 class TIntermBinary;
45 class TIntermUnary;
46 class TIntermConstantUnion;
47 class TIntermTernary;
48 class TIntermIfElse;
49 class TIntermSwitch;
50 class TIntermCase;
51 class TIntermTyped;
52 class TIntermSymbol;
53 class TIntermLoop;
54 class TInfoSink;
55 class TInfoSinkBase;
56 class TIntermRaw;
57 class TIntermBranch;
58 
59 class TSymbolTable;
60 class TFunction;
61 
62 // Encapsulate an identifier string and track whether it is coming from the original shader code
63 // (not internal) or from ANGLE (internal). Usually internal names shouldn't be decorated or hashed.
64 class TName
65 {
66   public:
67     POOL_ALLOCATOR_NEW_DELETE();
TName(const TString & name)68     explicit TName(const TString &name) : mName(name), mIsInternal(false) {}
TName()69     TName() : mName(), mIsInternal(false) {}
70     TName(const TName &) = default;
71     TName &operator=(const TName &) = default;
72 
getString()73     const TString &getString() const { return mName; }
setString(const TString & string)74     void setString(const TString &string) { mName = string; }
isInternal()75     bool isInternal() const { return mIsInternal; }
setInternal(bool isInternal)76     void setInternal(bool isInternal) { mIsInternal = isInternal; }
77 
78   private:
79     TString mName;
80     bool mIsInternal;
81 };
82 
83 //
84 // Base class for the tree nodes
85 //
86 class TIntermNode : angle::NonCopyable
87 {
88   public:
89     POOL_ALLOCATOR_NEW_DELETE();
TIntermNode()90     TIntermNode()
91     {
92         // TODO: Move this to TSourceLoc constructor
93         // after getting rid of TPublicType.
94         mLine.first_file = mLine.last_file = 0;
95         mLine.first_line = mLine.last_line = 0;
96     }
~TIntermNode()97     virtual ~TIntermNode() {}
98 
getLine()99     const TSourceLoc &getLine() const { return mLine; }
setLine(const TSourceLoc & l)100     void setLine(const TSourceLoc &l) { mLine = l; }
101 
102     virtual void traverse(TIntermTraverser *) = 0;
getAsTyped()103     virtual TIntermTyped *getAsTyped() { return 0; }
getAsConstantUnion()104     virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
getAsFunctionDefinition()105     virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
getAsAggregate()106     virtual TIntermAggregate *getAsAggregate() { return 0; }
getAsBlock()107     virtual TIntermBlock *getAsBlock() { return nullptr; }
getAsFunctionPrototypeNode()108     virtual TIntermFunctionPrototype *getAsFunctionPrototypeNode() { return nullptr; }
getAsInvariantDeclarationNode()109     virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() { return nullptr; }
getAsDeclarationNode()110     virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
getAsSwizzleNode()111     virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
getAsBinaryNode()112     virtual TIntermBinary *getAsBinaryNode() { return 0; }
getAsUnaryNode()113     virtual TIntermUnary *getAsUnaryNode() { return 0; }
getAsTernaryNode()114     virtual TIntermTernary *getAsTernaryNode() { return nullptr; }
getAsIfElseNode()115     virtual TIntermIfElse *getAsIfElseNode() { return nullptr; }
getAsSwitchNode()116     virtual TIntermSwitch *getAsSwitchNode() { return 0; }
getAsCaseNode()117     virtual TIntermCase *getAsCaseNode() { return 0; }
getAsSymbolNode()118     virtual TIntermSymbol *getAsSymbolNode() { return 0; }
getAsLoopNode()119     virtual TIntermLoop *getAsLoopNode() { return 0; }
getAsRawNode()120     virtual TIntermRaw *getAsRawNode() { return 0; }
getAsBranchNode()121     virtual TIntermBranch *getAsBranchNode() { return 0; }
122 
123     // Replace a child node. Return true if |original| is a child
124     // node and it is replaced; otherwise, return false.
125     virtual bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) = 0;
126 
127   protected:
128     TSourceLoc mLine;
129 };
130 
131 //
132 // This is just to help yacc.
133 //
134 struct TIntermNodePair
135 {
136     TIntermNode *node1;
137     TIntermNode *node2;
138 };
139 
140 //
141 // Intermediate class for nodes that have a type.
142 //
143 class TIntermTyped : public TIntermNode
144 {
145   public:
TIntermTyped(const TType & t)146     TIntermTyped(const TType &t) : mType(t) {}
147 
148     virtual TIntermTyped *deepCopy() const = 0;
149 
getAsTyped()150     TIntermTyped *getAsTyped() override { return this; }
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 
setType(const TType & t)157     void setType(const TType &t) { mType = t; }
158     void setTypePreservePrecision(const TType &t);
getType()159     const TType &getType() const { return mType; }
getTypePointer()160     TType *getTypePointer() { return &mType; }
161 
getBasicType()162     TBasicType getBasicType() const { return mType.getBasicType(); }
getQualifier()163     TQualifier getQualifier() const { return mType.getQualifier(); }
getPrecision()164     TPrecision getPrecision() const { return mType.getPrecision(); }
getMemoryQualifier()165     TMemoryQualifier getMemoryQualifier() const { return mType.getMemoryQualifier(); }
getCols()166     int getCols() const { return mType.getCols(); }
getRows()167     int getRows() const { return mType.getRows(); }
getNominalSize()168     int getNominalSize() const { return mType.getNominalSize(); }
getSecondarySize()169     int getSecondarySize() const { return mType.getSecondarySize(); }
170 
isInterfaceBlock()171     bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
isMatrix()172     bool isMatrix() const { return mType.isMatrix(); }
isArray()173     bool isArray() const { return mType.isArray(); }
isVector()174     bool isVector() const { return mType.isVector(); }
isScalar()175     bool isScalar() const { return mType.isScalar(); }
isScalarInt()176     bool isScalarInt() const { return mType.isScalarInt(); }
getBasicString()177     const char *getBasicString() const { return mType.getBasicString(); }
getCompleteString()178     TString getCompleteString() const { return mType.getCompleteString(); }
179 
getOutermostArraySize()180     unsigned int getOutermostArraySize() const { return mType.getOutermostArraySize(); }
181 
182     bool isConstructorWithOnlyConstantUnionParameters();
183 
184   protected:
185     TType mType;
186 
187     TIntermTyped(const TIntermTyped &node);
188 };
189 
190 //
191 // Handle for, do-while, and while loops.
192 //
193 enum TLoopType
194 {
195     ELoopFor,
196     ELoopWhile,
197     ELoopDoWhile
198 };
199 
200 class TIntermLoop : public TIntermNode
201 {
202   public:
203     TIntermLoop(TLoopType type,
204                 TIntermNode *init,
205                 TIntermTyped *cond,
206                 TIntermTyped *expr,
207                 TIntermBlock *body);
208 
getAsLoopNode()209     TIntermLoop *getAsLoopNode() override { return this; }
210     void traverse(TIntermTraverser *it) override;
211     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
212 
getType()213     TLoopType getType() const { return mType; }
getInit()214     TIntermNode *getInit() { return mInit; }
getCondition()215     TIntermTyped *getCondition() { return mCond; }
getExpression()216     TIntermTyped *getExpression() { return mExpr; }
getBody()217     TIntermBlock *getBody() { return mBody; }
218 
setInit(TIntermNode * init)219     void setInit(TIntermNode *init) { mInit = init; }
setCondition(TIntermTyped * condition)220     void setCondition(TIntermTyped *condition) { mCond = condition; }
setExpression(TIntermTyped * expression)221     void setExpression(TIntermTyped *expression) { mExpr = expression; }
setBody(TIntermBlock * body)222     void setBody(TIntermBlock *body) { mBody = body; }
223 
224   protected:
225     TLoopType mType;
226     TIntermNode *mInit;   // for-loop initialization
227     TIntermTyped *mCond;  // loop exit condition
228     TIntermTyped *mExpr;  // for-loop expression
229     TIntermBlock *mBody;  // loop body
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 
240     void traverse(TIntermTraverser *it) override;
getAsBranchNode()241     TIntermBranch *getAsBranchNode() override { return this; }
242     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
243 
getFlowOp()244     TOperator getFlowOp() { return mFlowOp; }
getExpression()245     TIntermTyped *getExpression() { return mExpression; }
246 
247   protected:
248     TOperator mFlowOp;
249     TIntermTyped *mExpression;  // non-zero except for "return exp;" statements
250 };
251 
252 //
253 // Nodes that correspond to symbols or constants in the source code.
254 //
255 class TIntermSymbol : public TIntermTyped
256 {
257   public:
258     // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
259     // If sym comes from per process globalpoolallocator, then it causes increased memory usage
260     // per compile it is essential to use "symbol = sym" to assign to symbol
TIntermSymbol(const TSymbolUniqueId & id,const TString & symbol,const TType & type)261     TIntermSymbol(const TSymbolUniqueId &id, const TString &symbol, const TType &type)
262         : TIntermTyped(type), mId(id), mSymbol(symbol)
263     {
264     }
265 
deepCopy()266     TIntermTyped *deepCopy() const override { return new TIntermSymbol(*this); }
267 
hasSideEffects()268     bool hasSideEffects() const override { return false; }
269 
getId()270     int getId() const { return mId.get(); }
getSymbol()271     const TString &getSymbol() const { return mSymbol.getString(); }
getName()272     const TName &getName() const { return mSymbol; }
getName()273     TName &getName() { return mSymbol; }
274 
setInternal(bool internal)275     void setInternal(bool internal) { mSymbol.setInternal(internal); }
276 
277     void traverse(TIntermTraverser *it) override;
getAsSymbolNode()278     TIntermSymbol *getAsSymbolNode() override { return this; }
replaceChildNode(TIntermNode *,TIntermNode *)279     bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
280 
281   protected:
282     const TSymbolUniqueId mId;
283     TName mSymbol;
284 
285   private:
286     TIntermSymbol(const TIntermSymbol &) = default;  // Note: not deleted, just private!
287 };
288 
289 // A Raw node stores raw code, that the translator will insert verbatim
290 // into the output stream. Useful for transformation operations that make
291 // complex code that might not fit naturally into the GLSL model.
292 class TIntermRaw : public TIntermTyped
293 {
294   public:
TIntermRaw(const TType & type,const TString & rawText)295     TIntermRaw(const TType &type, const TString &rawText) : TIntermTyped(type), mRawText(rawText) {}
296     TIntermRaw(const TIntermRaw &) = delete;
297 
deepCopy()298     TIntermTyped *deepCopy() const override
299     {
300         UNREACHABLE();
301         return nullptr;
302     }
303 
hasSideEffects()304     bool hasSideEffects() const override { return false; }
305 
getRawText()306     TString getRawText() const { return mRawText; }
307 
308     void traverse(TIntermTraverser *it) override;
309 
getAsRawNode()310     TIntermRaw *getAsRawNode() override { return this; }
replaceChildNode(TIntermNode *,TIntermNode *)311     bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
312 
313   protected:
314     TString mRawText;
315 };
316 
317 // Constant folded node.
318 // Note that nodes may be constant folded and not be constant expressions with the EvqConst
319 // qualifier. This happens for example when the following expression is processed:
320 // "true ? 1.0 : non_constant"
321 // Other nodes than TIntermConstantUnion may also be constant expressions.
322 //
323 class TIntermConstantUnion : public TIntermTyped
324 {
325   public:
TIntermConstantUnion(const TConstantUnion * unionPointer,const TType & type)326     TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
327         : TIntermTyped(type), mUnionArrayPointer(unionPointer)
328     {
329         ASSERT(unionPointer);
330     }
331 
deepCopy()332     TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
333 
hasSideEffects()334     bool hasSideEffects() const override { return false; }
335 
getUnionArrayPointer()336     const TConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
337 
getIConst(size_t index)338     int getIConst(size_t index) const
339     {
340         return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
341     }
getUConst(size_t index)342     unsigned int getUConst(size_t index) const
343     {
344         return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
345     }
getFConst(size_t index)346     float getFConst(size_t index) const
347     {
348         return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
349     }
getBConst(size_t index)350     bool getBConst(size_t index) const
351     {
352         return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
353     }
354 
replaceConstantUnion(const TConstantUnion * safeConstantUnion)355     void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
356     {
357         ASSERT(safeConstantUnion);
358         // Previous union pointer freed on pool deallocation.
359         mUnionArrayPointer = safeConstantUnion;
360     }
361 
getAsConstantUnion()362     TIntermConstantUnion *getAsConstantUnion() override { return this; }
363     void traverse(TIntermTraverser *it) override;
replaceChildNode(TIntermNode *,TIntermNode *)364     bool replaceChildNode(TIntermNode *, TIntermNode *) override { return false; }
365 
366     TConstantUnion *foldBinary(TOperator op,
367                                TIntermConstantUnion *rightNode,
368                                TDiagnostics *diagnostics,
369                                const TSourceLoc &line);
370     const TConstantUnion *foldIndexing(int index);
371     TConstantUnion *foldUnaryNonComponentWise(TOperator op);
372     TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
373 
374     static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
375     static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
376                                                 TDiagnostics *diagnostics);
377 
378   protected:
379     // Same data may be shared between multiple constant unions, so it can't be modified.
380     const TConstantUnion *mUnionArrayPointer;
381 
382   private:
383     typedef float (*FloatTypeUnaryFunc)(float);
384     void foldFloatTypeUnary(const TConstantUnion &parameter,
385                             FloatTypeUnaryFunc builtinFunc,
386                             TConstantUnion *result) const;
387 
388     TIntermConstantUnion(const TIntermConstantUnion &node);  // Note: not deleted, just private!
389 };
390 
391 //
392 // Intermediate class for node types that hold operators.
393 //
394 class TIntermOperator : public TIntermTyped
395 {
396   public:
getOp()397     TOperator getOp() const { return mOp; }
398 
399     bool isAssignment() const;
400     bool isMultiplication() const;
401     bool isConstructor() const;
402 
403     // Returns true for calls mapped to EOpCall*, false for built-ins that have their own specific
404     // ops.
405     bool isFunctionCall() const;
406 
hasSideEffects()407     bool hasSideEffects() const override { return isAssignment(); }
408 
409   protected:
TIntermOperator(TOperator op)410     TIntermOperator(TOperator op) : TIntermTyped(TType(EbtFloat, EbpUndefined)), mOp(op) {}
TIntermOperator(TOperator op,const TType & type)411     TIntermOperator(TOperator op, const TType &type) : TIntermTyped(type), mOp(op) {}
412 
413     TIntermOperator(const TIntermOperator &) = default;
414 
415     const TOperator mOp;
416 };
417 
418 // Node for vector swizzles.
419 class TIntermSwizzle : public TIntermTyped
420 {
421   public:
422     // This constructor determines the type of the node based on the operand.
423     TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets);
424 
deepCopy()425     TIntermTyped *deepCopy() const override { return new TIntermSwizzle(*this); }
426 
getAsSwizzleNode()427     TIntermSwizzle *getAsSwizzleNode() override { return this; };
428     void traverse(TIntermTraverser *it) override;
429     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
430 
hasSideEffects()431     bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
432 
getOperand()433     TIntermTyped *getOperand() { return mOperand; }
434     void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
435 
436     bool hasDuplicateOffsets() const;
437     bool offsetsMatch(int offset) const;
438 
439     TIntermTyped *fold();
440 
441   protected:
442     TIntermTyped *mOperand;
443     TVector<int> mSwizzleOffsets;
444 
445   private:
446     void promote();
447 
448     TIntermSwizzle(const TIntermSwizzle &node);  // Note: not deleted, just private!
449 };
450 
451 //
452 // Nodes for all the basic binary math operators.
453 //
454 class TIntermBinary : public TIntermOperator
455 {
456   public:
457     // This constructor determines the type of the binary node based on the operands and op.
458     TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
459 
deepCopy()460     TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
461 
462     static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
463     static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
464     static TQualifier GetCommaQualifier(int shaderVersion,
465                                         const TIntermTyped *left,
466                                         const TIntermTyped *right);
467 
getAsBinaryNode()468     TIntermBinary *getAsBinaryNode() override { return this; };
469     void traverse(TIntermTraverser *it) override;
470     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
471 
hasSideEffects()472     bool hasSideEffects() const override
473     {
474         return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
475     }
476 
getLeft()477     TIntermTyped *getLeft() const { return mLeft; }
getRight()478     TIntermTyped *getRight() const { return mRight; }
479     TIntermTyped *fold(TDiagnostics *diagnostics);
480 
setAddIndexClamp()481     void setAddIndexClamp() { mAddIndexClamp = true; }
getAddIndexClamp()482     bool getAddIndexClamp() { return mAddIndexClamp; }
483 
484   protected:
485     TIntermTyped *mLeft;
486     TIntermTyped *mRight;
487 
488     // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
489     bool mAddIndexClamp;
490 
491   private:
492     void promote();
493 
494     TIntermBinary(const TIntermBinary &node);  // Note: not deleted, just private!
495 };
496 
497 //
498 // Nodes for unary math operators.
499 //
500 class TIntermUnary : public TIntermOperator
501 {
502   public:
503     TIntermUnary(TOperator op, TIntermTyped *operand);
504 
deepCopy()505     TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
506 
507     void traverse(TIntermTraverser *it) override;
getAsUnaryNode()508     TIntermUnary *getAsUnaryNode() override { return this; }
509     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
510 
hasSideEffects()511     bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
512 
getOperand()513     TIntermTyped *getOperand() { return mOperand; }
514     TIntermTyped *fold(TDiagnostics *diagnostics);
515 
setUseEmulatedFunction()516     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
getUseEmulatedFunction()517     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
518 
519   protected:
520     TIntermTyped *mOperand;
521 
522     // If set to true, replace the built-in function call with an emulated one
523     // to work around driver bugs.
524     bool mUseEmulatedFunction;
525 
526   private:
527     void promote();
528 
529     TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
530 };
531 
532 class TFunctionSymbolInfo
533 {
534   public:
535     POOL_ALLOCATOR_NEW_DELETE();
536     TFunctionSymbolInfo(const TSymbolUniqueId &id);
TFunctionSymbolInfo()537     TFunctionSymbolInfo() : mId(nullptr), mKnownToNotHaveSideEffects(false) {}
538 
539     TFunctionSymbolInfo(const TFunctionSymbolInfo &info);
540     TFunctionSymbolInfo &operator=(const TFunctionSymbolInfo &info);
541 
542     void setFromFunction(const TFunction &function);
543 
setNameObj(const TName & name)544     void setNameObj(const TName &name) { mName = name; }
getNameObj()545     const TName &getNameObj() const { return mName; }
546 
getName()547     const TString &getName() const { return mName.getString(); }
setName(const TString & name)548     void setName(const TString &name) { mName.setString(name); }
isMain()549     bool isMain() const { return mName.getString() == "main"; }
550 
setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects)551     void setKnownToNotHaveSideEffects(bool knownToNotHaveSideEffects)
552     {
553         mKnownToNotHaveSideEffects = knownToNotHaveSideEffects;
554     }
isKnownToNotHaveSideEffects()555     bool isKnownToNotHaveSideEffects() const { return mKnownToNotHaveSideEffects; }
556 
557     void setId(const TSymbolUniqueId &functionId);
558     const TSymbolUniqueId &getId() const;
559 
isImageFunction()560     bool isImageFunction() const
561     {
562         return getName() == "imageSize" || getName() == "imageLoad" || getName() == "imageStore";
563     }
564 
565   private:
566     TName mName;
567     TSymbolUniqueId *mId;
568     bool mKnownToNotHaveSideEffects;
569 };
570 
571 typedef TVector<TIntermNode *> TIntermSequence;
572 typedef TVector<int> TQualifierList;
573 
574 //
575 // This is just to help yacc.
576 //
577 struct TIntermFunctionCallOrMethod
578 {
579     TIntermSequence *arguments;
580     TIntermNode *thisNode;
581 };
582 
583 // Interface for node classes that have an arbitrarily sized set of children.
584 class TIntermAggregateBase
585 {
586   public:
~TIntermAggregateBase()587     virtual ~TIntermAggregateBase() {}
588 
589     virtual TIntermSequence *getSequence()             = 0;
590     virtual const TIntermSequence *getSequence() const = 0;
591 
592     bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
593     bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
594 
595   protected:
TIntermAggregateBase()596     TIntermAggregateBase() {}
597 
598     bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
599 };
600 
601 //
602 // Nodes that operate on an arbitrary sized set of children.
603 //
604 class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
605 {
606   public:
607     static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
608 
609     // If using this, ensure that there's a consistent function definition with the same symbol id
610     // added to the AST.
611     static TIntermAggregate *CreateFunctionCall(const TType &type,
612                                                 const TSymbolUniqueId &id,
613                                                 const TName &name,
614                                                 TIntermSequence *arguments);
615 
616     static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
617                                                        TIntermSequence *arguments);
618     static TIntermAggregate *CreateConstructor(const TType &type,
619                                                TIntermSequence *arguments);
620     static TIntermAggregate *Create(const TType &type, TOperator op, TIntermSequence *arguments);
~TIntermAggregate()621     ~TIntermAggregate() {}
622 
623     // Note: only supported for nodes that can be a part of an expression.
deepCopy()624     TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
625 
626     TIntermAggregate *shallowCopy() const;
627 
getAsAggregate()628     TIntermAggregate *getAsAggregate() override { return this; }
629     void traverse(TIntermTraverser *it) override;
630     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
631 
632     bool hasSideEffects() const override;
633 
634     static bool CanFoldAggregateBuiltInOp(TOperator op);
635     TIntermTyped *fold(TDiagnostics *diagnostics);
636 
getSequence()637     TIntermSequence *getSequence() override { return &mArguments; }
getSequence()638     const TIntermSequence *getSequence() const override { return &mArguments; }
639 
640     TString getSymbolTableMangledName() const;
641 
setUseEmulatedFunction()642     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
getUseEmulatedFunction()643     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
644 
645     // Returns true if changing parameter precision may affect the return value.
gotPrecisionFromChildren()646     bool gotPrecisionFromChildren() const { return mGotPrecisionFromChildren; }
647 
getFunctionSymbolInfo()648     TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
getFunctionSymbolInfo()649     const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
650 
651   protected:
652     TIntermSequence mArguments;
653 
654     // If set to true, replace the built-in function call with an emulated one
655     // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
656     bool mUseEmulatedFunction;
657 
658     bool mGotPrecisionFromChildren;
659 
660     TFunctionSymbolInfo mFunctionInfo;
661 
662   private:
663     TIntermAggregate(const TType &type, TOperator op, TIntermSequence *arguments);
664 
665     TIntermAggregate(const TIntermAggregate &node);  // note: not deleted, just private!
666 
667     void setTypePrecisionAndQualifier(const TType &type);
668 
669     bool areChildrenConstQualified();
670 
671     void setPrecisionFromChildren();
672 
673     void setPrecisionForBuiltInOp();
674 
675     // Returns true if precision was set according to special rules for this built-in.
676     bool setPrecisionForSpecialBuiltInOp();
677 
678     // Used for built-in functions under EOpCallBuiltInFunction. The function name in the symbol
679     // info needs to be set before calling this.
680     void setBuiltInFunctionPrecision();
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() {}
~TIntermBlock()689     ~TIntermBlock() {}
690 
getAsBlock()691     TIntermBlock *getAsBlock() override { return this; }
692     void traverse(TIntermTraverser *it) override;
693     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
694 
695     // Only intended for initially building the block.
696     void appendStatement(TIntermNode *statement);
697 
getSequence()698     TIntermSequence *getSequence() override { return &mStatements; }
getSequence()699     const TIntermSequence *getSequence() const override { return &mStatements; }
700 
701   protected:
702     TIntermSequence mStatements;
703 };
704 
705 // Function prototype. May be in the AST either as a function prototype declaration or as a part of
706 // a function definition. The type of the node is the function return type.
707 class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
708 {
709   public:
710     // TODO(oetuaho@nvidia.com): See if TFunctionSymbolInfo could be added to constructor
711     // parameters.
TIntermFunctionPrototype(const TType & type,const TSymbolUniqueId & id)712     TIntermFunctionPrototype(const TType &type, const TSymbolUniqueId &id)
713         : TIntermTyped(type), mFunctionInfo(id)
714     {
715     }
~TIntermFunctionPrototype()716     ~TIntermFunctionPrototype() {}
717 
getAsFunctionPrototypeNode()718     TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
719     void traverse(TIntermTraverser *it) override;
720     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
721 
deepCopy()722     TIntermTyped *deepCopy() const override
723     {
724         UNREACHABLE();
725         return nullptr;
726     }
hasSideEffects()727     bool hasSideEffects() const override
728     {
729         UNREACHABLE();
730         return true;
731     }
732 
733     // Only intended for initially building the declaration.
734     void appendParameter(TIntermSymbol *parameter);
735 
getSequence()736     TIntermSequence *getSequence() override { return &mParameters; }
getSequence()737     const TIntermSequence *getSequence() const override { return &mParameters; }
738 
getFunctionSymbolInfo()739     TFunctionSymbolInfo *getFunctionSymbolInfo() { return &mFunctionInfo; }
getFunctionSymbolInfo()740     const TFunctionSymbolInfo *getFunctionSymbolInfo() const { return &mFunctionInfo; }
741 
742   protected:
743     TIntermSequence mParameters;
744 
745     TFunctionSymbolInfo mFunctionInfo;
746 };
747 
748 // Node for function definitions. The prototype child node stores the function header including
749 // parameters, and the body child node stores the function body.
750 class TIntermFunctionDefinition : public TIntermNode
751 {
752   public:
TIntermFunctionDefinition(TIntermFunctionPrototype * prototype,TIntermBlock * body)753     TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
754         : TIntermNode(), mPrototype(prototype), mBody(body)
755     {
756         ASSERT(prototype != nullptr);
757         ASSERT(body != nullptr);
758     }
759 
getAsFunctionDefinition()760     TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
761     void traverse(TIntermTraverser *it) override;
762     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
763 
getFunctionPrototype()764     TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
getBody()765     TIntermBlock *getBody() const { return mBody; }
766 
getFunctionSymbolInfo()767     const TFunctionSymbolInfo *getFunctionSymbolInfo() const
768     {
769         return mPrototype->getFunctionSymbolInfo();
770     }
771 
772   private:
773     TIntermFunctionPrototype *mPrototype;
774     TIntermBlock *mBody;
775 };
776 
777 // Struct, interface block or variable declaration. Can contain multiple variable declarators.
778 class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
779 {
780   public:
TIntermDeclaration()781     TIntermDeclaration() : TIntermNode() {}
~TIntermDeclaration()782     ~TIntermDeclaration() {}
783 
getAsDeclarationNode()784     TIntermDeclaration *getAsDeclarationNode() override { return this; }
785     void traverse(TIntermTraverser *it) override;
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   protected:
796     TIntermSequence mDeclarators;
797 };
798 
799 // Specialized declarations for attributing invariance.
800 class TIntermInvariantDeclaration : public TIntermNode
801 {
802   public:
803     TIntermInvariantDeclaration(TIntermSymbol *symbol, const TSourceLoc &line);
804 
getAsInvariantDeclarationNode()805     virtual TIntermInvariantDeclaration *getAsInvariantDeclarationNode() override { return this; }
806 
getSymbol()807     TIntermSymbol *getSymbol() { return mSymbol; }
808 
809     void traverse(TIntermTraverser *it) override;
810     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
811 
812   private:
813     TIntermSymbol *mSymbol;
814 };
815 
816 // For ternary operators like a ? b : c.
817 class TIntermTernary : public TIntermTyped
818 {
819   public:
820     TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
821 
822     void traverse(TIntermTraverser *it) override;
823     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
824 
getCondition()825     TIntermTyped *getCondition() const { return mCondition; }
getTrueExpression()826     TIntermTyped *getTrueExpression() const { return mTrueExpression; }
getFalseExpression()827     TIntermTyped *getFalseExpression() const { return mFalseExpression; }
getAsTernaryNode()828     TIntermTernary *getAsTernaryNode() override { return this; }
829 
deepCopy()830     TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
831 
hasSideEffects()832     bool hasSideEffects() const override
833     {
834         return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
835                mFalseExpression->hasSideEffects();
836     }
837 
838     TIntermTyped *fold();
839 
840   private:
841     TIntermTernary(const TIntermTernary &node);  // Note: not deleted, just private!
842 
843     static TQualifier DetermineQualifier(TIntermTyped *cond,
844                                          TIntermTyped *trueExpression,
845                                          TIntermTyped *falseExpression);
846 
847     TIntermTyped *mCondition;
848     TIntermTyped *mTrueExpression;
849     TIntermTyped *mFalseExpression;
850 };
851 
852 class TIntermIfElse : public TIntermNode
853 {
854   public:
855     TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
856 
857     void traverse(TIntermTraverser *it) override;
858     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
859 
getCondition()860     TIntermTyped *getCondition() const { return mCondition; }
getTrueBlock()861     TIntermBlock *getTrueBlock() const { return mTrueBlock; }
getFalseBlock()862     TIntermBlock *getFalseBlock() const { return mFalseBlock; }
getAsIfElseNode()863     TIntermIfElse *getAsIfElseNode() override { return this; }
864 
865   protected:
866     TIntermTyped *mCondition;
867     TIntermBlock *mTrueBlock;
868     TIntermBlock *mFalseBlock;
869 };
870 
871 //
872 // Switch statement.
873 //
874 class TIntermSwitch : public TIntermNode
875 {
876   public:
877     TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
878 
879     void traverse(TIntermTraverser *it) override;
880     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
881 
getAsSwitchNode()882     TIntermSwitch *getAsSwitchNode() override { return this; }
883 
getInit()884     TIntermTyped *getInit() { return mInit; }
getStatementList()885     TIntermBlock *getStatementList() { return mStatementList; }
886 
887     // Must be called with a non-null statementList.
888     void setStatementList(TIntermBlock *statementList);
889 
890   protected:
891     TIntermTyped *mInit;
892     TIntermBlock *mStatementList;
893 };
894 
895 //
896 // Case label.
897 //
898 class TIntermCase : public TIntermNode
899 {
900   public:
TIntermCase(TIntermTyped * condition)901     TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
902 
903     void traverse(TIntermTraverser *it) override;
904     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
905 
getAsCaseNode()906     TIntermCase *getAsCaseNode() override { return this; }
907 
hasCondition()908     bool hasCondition() const { return mCondition != nullptr; }
getCondition()909     TIntermTyped *getCondition() const { return mCondition; }
910 
911   protected:
912     TIntermTyped *mCondition;
913 };
914 
915 }  // namespace sh
916 
917 #endif  // COMPILER_TRANSLATOR_INTERMNODE_H_
918