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