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