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 ImmutableString getOffsetsAsXYZW() const;
467 void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
468
getSwizzleOffsets()469 const TVector<int> &getSwizzleOffsets() { return mSwizzleOffsets; }
470
471 bool hasDuplicateOffsets() const;
472 void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
473 bool offsetsMatch(int offset) const;
474
475 TIntermTyped *fold(TDiagnostics *diagnostics) override;
476
477 protected:
478 TIntermTyped *mOperand;
479 TVector<int> mSwizzleOffsets;
480 bool mHasFoldedDuplicateOffsets;
481
482 private:
483 void promote();
484 TPrecision derivePrecision() const override;
485 void propagatePrecision(TPrecision precision) override;
486
487 TIntermSwizzle(const TIntermSwizzle &node); // Note: not deleted, just private!
488 };
489
490 //
491 // Nodes for all the basic binary math operators.
492 //
493 class TIntermBinary : public TIntermOperator
494 {
495 public:
496 // This constructor determines the type of the binary node based on the operands and op.
497 TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right);
498 // Comma qualifier depends on the shader version, so use this to create comma nodes:
499 static TIntermBinary *CreateComma(TIntermTyped *left, TIntermTyped *right, int shaderVersion);
500
deepCopy()501 TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
502
503 bool hasConstantValue() const override;
504 const TConstantUnion *getConstantValue() const override;
505
506 static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
507 static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
508
getAsBinaryNode()509 TIntermBinary *getAsBinaryNode() override { return this; }
510 void traverse(TIntermTraverser *it) final;
511 bool visit(Visit visit, TIntermTraverser *it) final;
512
513 size_t getChildCount() const final;
514 TIntermNode *getChildNode(size_t index) const final;
515 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
516
hasSideEffects()517 bool hasSideEffects() const override
518 {
519 return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
520 }
521
getLeft()522 TIntermTyped *getLeft() const { return mLeft; }
getRight()523 TIntermTyped *getRight() const { return mRight; }
524 TIntermTyped *fold(TDiagnostics *diagnostics) override;
525
526 // This method is only valid for EOpIndexDirectStruct. It returns the name of the field.
527 const ImmutableString &getIndexStructFieldName() const;
528
529 protected:
530 TIntermTyped *mLeft;
531 TIntermTyped *mRight;
532
533 private:
534 void promote();
535 TPrecision derivePrecision() const override;
536 void propagatePrecision(TPrecision precision) override;
537
538 static TQualifier GetCommaQualifier(int shaderVersion,
539 const TIntermTyped *left,
540 const TIntermTyped *right);
541
542 TIntermBinary(const TIntermBinary &node); // Note: not deleted, just private!
543 };
544
545 //
546 // Nodes for unary math operators.
547 //
548 class TIntermUnary : public TIntermOperator
549 {
550 public:
551 TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
552
deepCopy()553 TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
554
getAsUnaryNode()555 TIntermUnary *getAsUnaryNode() override { return this; }
556 void traverse(TIntermTraverser *it) final;
557 bool visit(Visit visit, TIntermTraverser *it) final;
558
559 size_t getChildCount() const final;
560 TIntermNode *getChildNode(size_t index) const final;
561 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
562
hasSideEffects()563 bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
564
getOperand()565 TIntermTyped *getOperand() { return mOperand; }
566 TIntermTyped *fold(TDiagnostics *diagnostics) override;
567
getFunction()568 const TFunction *getFunction() const { return mFunction; }
569
setUseEmulatedFunction()570 void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
getUseEmulatedFunction()571 bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
572
573 protected:
574 TIntermTyped *mOperand;
575
576 // If set to true, replace the built-in function call with an emulated one
577 // to work around driver bugs.
578 bool mUseEmulatedFunction;
579
580 const TFunction *const mFunction;
581
582 private:
583 void promote();
584 TPrecision derivePrecision() const override;
585 void propagatePrecision(TPrecision precision) override;
586
587 TIntermUnary(const TIntermUnary &node); // note: not deleted, just private!
588 };
589
590 typedef TVector<TIntermNode *> TIntermSequence;
591 typedef TVector<int> TQualifierList;
592
593 // Interface for node classes that have an arbitrarily sized set of children.
594 class TIntermAggregateBase
595 {
596 public:
~TIntermAggregateBase()597 virtual ~TIntermAggregateBase() {}
598
599 virtual TIntermSequence *getSequence() = 0;
600 virtual const TIntermSequence *getSequence() const = 0;
601
602 bool replaceChildNodeWithMultiple(TIntermNode *original, const TIntermSequence &replacements);
603 bool insertChildNodes(TIntermSequence::size_type position, const TIntermSequence &insertions);
604
605 protected:
TIntermAggregateBase()606 TIntermAggregateBase() {}
607
608 bool replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement);
609 };
610
611 //
612 // Nodes that operate on an arbitrary sized set of children.
613 //
614 class TIntermAggregate : public TIntermOperator, public TIntermAggregateBase
615 {
616 public:
617 static TIntermAggregate *CreateFunctionCall(const TFunction &func, TIntermSequence *arguments);
618
619 static TIntermAggregate *CreateRawFunctionCall(const TFunction &func,
620 TIntermSequence *arguments);
621
622 // This covers all built-in function calls.
623 static TIntermAggregate *CreateBuiltInFunctionCall(const TFunction &func,
624 TIntermSequence *arguments);
625 static TIntermAggregate *CreateConstructor(const TType &type, TIntermSequence *arguments);
626 static TIntermAggregate *CreateConstructor(
627 const TType &type,
628 const std::initializer_list<TIntermNode *> &arguments);
~TIntermAggregate()629 ~TIntermAggregate() override {}
630
631 // Note: only supported for nodes that can be a part of an expression.
deepCopy()632 TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); }
633
634 TIntermAggregate *shallowCopy() const;
635
636 bool hasConstantValue() const override;
637 bool isConstantNullValue() const override;
638 const TConstantUnion *getConstantValue() const override;
639
getAsAggregate()640 TIntermAggregate *getAsAggregate() override { return this; }
641 void traverse(TIntermTraverser *it) final;
642 bool visit(Visit visit, TIntermTraverser *it) final;
643
644 size_t getChildCount() const final;
645 TIntermNode *getChildNode(size_t index) const final;
646 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
647
648 bool hasSideEffects() const override;
649
650 TIntermTyped *fold(TDiagnostics *diagnostics) override;
651
getSequence()652 TIntermSequence *getSequence() override { return &mArguments; }
getSequence()653 const TIntermSequence *getSequence() const override { return &mArguments; }
654
setUseEmulatedFunction()655 void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
getUseEmulatedFunction()656 bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
657
getFunction()658 const TFunction *getFunction() const { return mFunction; }
659
660 // Get the function name to display to the user in an error message.
661 const char *functionName() const;
662
663 protected:
664 TIntermSequence mArguments;
665
666 // If set to true, replace the built-in function call with an emulated one
667 // to work around driver bugs. Only for calls mapped to ops other than EOpCall*.
668 bool mUseEmulatedFunction;
669
670 const TFunction *const mFunction;
671
672 private:
673 TIntermAggregate(const TFunction *func,
674 const TType &type,
675 TOperator op,
676 TIntermSequence *arguments);
677
678 TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private!
679
680 void setPrecisionAndQualifier();
681 TPrecision derivePrecision() const override;
682 void propagatePrecision(TPrecision precision) override;
683
684 bool areChildrenConstQualified();
685 };
686
687 // A list of statements. Either the root node which contains declarations and function definitions,
688 // or a block that can be marked with curly braces {}.
689 class TIntermBlock : public TIntermNode, public TIntermAggregateBase
690 {
691 public:
TIntermBlock()692 TIntermBlock() : TIntermNode(), mIsTreeRoot(false) {}
693 TIntermBlock(std::initializer_list<TIntermNode *> stmts);
~TIntermBlock()694 ~TIntermBlock() override {}
695
getAsBlock()696 TIntermBlock *getAsBlock() override { return this; }
697 void traverse(TIntermTraverser *it) final;
698 bool visit(Visit visit, TIntermTraverser *it) final;
699
700 size_t getChildCount() const final;
701 TIntermNode *getChildNode(size_t index) const final;
702 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
703 void replaceAllChildren(const TIntermSequence &newStatements);
704
705 // Only intended for initially building the block.
706 void appendStatement(TIntermNode *statement);
707 void insertStatement(size_t insertPosition, TIntermNode *statement);
708
getSequence()709 TIntermSequence *getSequence() override { return &mStatements; }
getSequence()710 const TIntermSequence *getSequence() const override { return &mStatements; }
711
deepCopy()712 TIntermBlock *deepCopy() const override { return new TIntermBlock(*this); }
713
setIsTreeRoot()714 void setIsTreeRoot() { mIsTreeRoot = true; }
isTreeRoot()715 bool isTreeRoot() const { return mIsTreeRoot; }
716
717 protected:
718 TIntermSequence mStatements;
719
720 // Used to distinguish the tree root from the other blocks. When validating the AST, some
721 // validations are not applicable if not run on the entire tree and are thus skipped.
722 bool mIsTreeRoot;
723
724 private:
725 TIntermBlock(const TIntermBlock &);
726 };
727
728 // Function prototype. May be in the AST either as a function prototype declaration or as a part of
729 // a function definition. The type of the node is the function return type.
730 class TIntermFunctionPrototype : public TIntermTyped
731 {
732 public:
733 TIntermFunctionPrototype(const TFunction *function);
~TIntermFunctionPrototype()734 ~TIntermFunctionPrototype() override {}
735
getAsFunctionPrototypeNode()736 TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
737 void traverse(TIntermTraverser *it) final;
738 bool visit(Visit visit, TIntermTraverser *it) final;
739
740 size_t getChildCount() const final;
741 TIntermNode *getChildNode(size_t index) const final;
742 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
743
744 const TType &getType() const override;
745
deepCopy()746 TIntermTyped *deepCopy() const override
747 {
748 UNREACHABLE();
749 return nullptr;
750 }
hasSideEffects()751 bool hasSideEffects() const override
752 {
753 UNREACHABLE();
754 return true;
755 }
756
getFunction()757 const TFunction *getFunction() const { return mFunction; }
758
759 protected:
760 const TFunction *const mFunction;
761 };
762
763 // Node for function definitions. The prototype child node stores the function header including
764 // parameters, and the body child node stores the function body.
765 class TIntermFunctionDefinition : public TIntermNode
766 {
767 public:
TIntermFunctionDefinition(TIntermFunctionPrototype * prototype,TIntermBlock * body)768 TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body)
769 : TIntermNode(), mPrototype(prototype), mBody(body)
770 {
771 ASSERT(prototype != nullptr);
772 ASSERT(body != nullptr);
773 }
774
getAsFunctionDefinition()775 TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; }
776 void traverse(TIntermTraverser *it) final;
777 bool visit(Visit visit, TIntermTraverser *it) final;
778
779 size_t getChildCount() const final;
780 TIntermNode *getChildNode(size_t index) const final;
781 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
782
getFunctionPrototype()783 TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; }
getBody()784 TIntermBlock *getBody() const { return mBody; }
785
getFunction()786 const TFunction *getFunction() const { return mPrototype->getFunction(); }
787
deepCopy()788 TIntermNode *deepCopy() const override
789 {
790 UNREACHABLE();
791 return nullptr;
792 }
793
794 private:
795 TIntermFunctionPrototype *mPrototype;
796 TIntermBlock *mBody;
797 };
798
799 // Struct, interface block or variable declaration. Can contain multiple variable declarators.
800 class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
801 {
802 public:
TIntermDeclaration()803 TIntermDeclaration() : TIntermNode() {}
804 TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr);
805 TIntermDeclaration(std::initializer_list<const TVariable *> declarators);
806 TIntermDeclaration(std::initializer_list<TIntermTyped *> declarators);
~TIntermDeclaration()807 ~TIntermDeclaration() override {}
808
getAsDeclarationNode()809 TIntermDeclaration *getAsDeclarationNode() override { return this; }
810 bool visit(Visit visit, TIntermTraverser *it) final;
811
812 size_t getChildCount() const final;
813 TIntermNode *getChildNode(size_t index) const final;
814 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
815
816 // Only intended for initially building the declaration.
817 // The declarator node should be either TIntermSymbol or TIntermBinary with op set to
818 // EOpInitialize.
819 void appendDeclarator(TIntermTyped *declarator);
820
getSequence()821 TIntermSequence *getSequence() override { return &mDeclarators; }
getSequence()822 const TIntermSequence *getSequence() const override { return &mDeclarators; }
823
deepCopy()824 TIntermDeclaration *deepCopy() const override
825 {
826 // Note: This is only useful as support for deepCopy of TIntermBlock and TIntermLoop, but is
827 // not sufficient as it will be redeclaring the same TVariable. If a function body is
828 // duplicated for example, it means that both functions reference the same TVariable pointer
829 // which works, but is technically not correct. In particular, maps with TVariable * as key
830 // can get confused.
831 //
832 // After deepCopy() is issued, ReplaceVariables must be used to replace every declared
833 // variable with a duplicate. This is NOT automatically done when deepCopy-ing TIntermBlock
834 // and TIntermLoop nodes.
835 return new TIntermDeclaration(*this);
836 }
837
838 protected:
839 TIntermDeclaration(const TIntermDeclaration &node);
840
841 TIntermSequence mDeclarators;
842 };
843
844 // Specialized declarations for attributing invariance.
845 class TIntermGlobalQualifierDeclaration : public TIntermNode
846 {
847 public:
848 TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol,
849 bool isPrecise,
850 const TSourceLoc &line);
851
getAsGlobalQualifierDeclarationNode()852 virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override
853 {
854 return this;
855 }
856 bool visit(Visit visit, TIntermTraverser *it) final;
857
getSymbol()858 TIntermSymbol *getSymbol() { return mSymbol; }
isInvariant()859 bool isInvariant() const { return !mIsPrecise; }
isPrecise()860 bool isPrecise() const { return mIsPrecise; }
861
862 size_t getChildCount() const final;
863 TIntermNode *getChildNode(size_t index) const final;
864 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
865
deepCopy()866 TIntermGlobalQualifierDeclaration *deepCopy() const override
867 {
868 return new TIntermGlobalQualifierDeclaration(*this);
869 }
870
871 private:
872 TIntermSymbol *mSymbol;
873 // Either |precise| or |invariant|, determined based on this flag.
874 bool mIsPrecise;
875
876 TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &);
877 };
878
879 // For ternary operators like a ? b : c.
880 class TIntermTernary : public TIntermExpression
881 {
882 public:
883 TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression);
884
getAsTernaryNode()885 TIntermTernary *getAsTernaryNode() override { return this; }
886 bool visit(Visit visit, TIntermTraverser *it) final;
887
888 size_t getChildCount() const final;
889 TIntermNode *getChildNode(size_t index) const final;
890 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
891
getCondition()892 TIntermTyped *getCondition() const { return mCondition; }
getTrueExpression()893 TIntermTyped *getTrueExpression() const { return mTrueExpression; }
getFalseExpression()894 TIntermTyped *getFalseExpression() const { return mFalseExpression; }
895
deepCopy()896 TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); }
897
hasSideEffects()898 bool hasSideEffects() const override
899 {
900 return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() ||
901 mFalseExpression->hasSideEffects();
902 }
903
904 TIntermTyped *fold(TDiagnostics *diagnostics) override;
905
906 private:
907 TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private!
908
909 static TQualifier DetermineQualifier(TIntermTyped *cond,
910 TIntermTyped *trueExpression,
911 TIntermTyped *falseExpression);
912 TPrecision derivePrecision() const override;
913 void propagatePrecision(TPrecision precision) override;
914
915 TIntermTyped *mCondition;
916 TIntermTyped *mTrueExpression;
917 TIntermTyped *mFalseExpression;
918 };
919
920 class TIntermIfElse : public TIntermNode
921 {
922 public:
923 TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB);
924
getAsIfElseNode()925 TIntermIfElse *getAsIfElseNode() override { return this; }
926 bool visit(Visit visit, TIntermTraverser *it) final;
927
928 size_t getChildCount() const final;
929 TIntermNode *getChildNode(size_t index) const final;
930 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
931
getCondition()932 TIntermTyped *getCondition() const { return mCondition; }
getTrueBlock()933 TIntermBlock *getTrueBlock() const { return mTrueBlock; }
getFalseBlock()934 TIntermBlock *getFalseBlock() const { return mFalseBlock; }
935
deepCopy()936 TIntermIfElse *deepCopy() const override { return new TIntermIfElse(*this); }
937
938 protected:
939 TIntermTyped *mCondition;
940 TIntermBlock *mTrueBlock;
941 TIntermBlock *mFalseBlock;
942
943 private:
944 TIntermIfElse(const TIntermIfElse &);
945 };
946
947 //
948 // Switch statement.
949 //
950 class TIntermSwitch : public TIntermNode
951 {
952 public:
953 TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList);
954
getAsSwitchNode()955 TIntermSwitch *getAsSwitchNode() override { return this; }
956 bool visit(Visit visit, TIntermTraverser *it) final;
957
958 size_t getChildCount() const final;
959 TIntermNode *getChildNode(size_t index) const final;
960 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
961
getInit()962 TIntermTyped *getInit() { return mInit; }
getStatementList()963 TIntermBlock *getStatementList() { return mStatementList; }
964
965 // Must be called with a non-null statementList.
966 void setStatementList(TIntermBlock *statementList);
967
deepCopy()968 TIntermSwitch *deepCopy() const override { return new TIntermSwitch(*this); }
969
970 protected:
971 TIntermTyped *mInit;
972 TIntermBlock *mStatementList;
973
974 private:
975 TIntermSwitch(const TIntermSwitch &);
976 };
977
978 //
979 // Case label.
980 //
981 class TIntermCase : public TIntermNode
982 {
983 public:
TIntermCase(TIntermTyped * condition)984 TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {}
985
getAsCaseNode()986 TIntermCase *getAsCaseNode() override { return this; }
987 bool visit(Visit visit, TIntermTraverser *it) final;
988
989 size_t getChildCount() const final;
990 TIntermNode *getChildNode(size_t index) const final;
991 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
992
hasCondition()993 bool hasCondition() const { return mCondition != nullptr; }
getCondition()994 TIntermTyped *getCondition() const { return mCondition; }
995
deepCopy()996 TIntermCase *deepCopy() const override { return new TIntermCase(*this); }
997
998 protected:
999 TIntermTyped *mCondition;
1000
1001 private:
1002 TIntermCase(const TIntermCase &);
1003 };
1004
1005 //
1006 // Preprocessor Directive.
1007 // #ifdef, #define, #if, #endif, etc.
1008 //
1009
1010 enum class PreprocessorDirective
1011 {
1012 Define,
1013 Ifdef,
1014 If,
1015 Endif,
1016 };
1017
1018 class TIntermPreprocessorDirective final : public TIntermNode
1019 {
1020 public:
1021 // This could also take an ImmutableString as an argument.
1022 TIntermPreprocessorDirective(PreprocessorDirective directive, ImmutableString command);
1023 ~TIntermPreprocessorDirective() final;
1024
1025 void traverse(TIntermTraverser *it) final;
1026 bool visit(Visit visit, TIntermTraverser *it) final;
replaceChildNode(TIntermNode *,TIntermNode *)1027 bool replaceChildNode(TIntermNode *, TIntermNode *) final { return false; }
1028
getAsPreprocessorDirective()1029 TIntermPreprocessorDirective *getAsPreprocessorDirective() final { return this; }
1030 size_t getChildCount() const final;
1031 TIntermNode *getChildNode(size_t index) const final;
1032
getDirective()1033 PreprocessorDirective getDirective() const { return mDirective; }
getCommand()1034 const ImmutableString &getCommand() const { return mCommand; }
1035
deepCopy()1036 TIntermPreprocessorDirective *deepCopy() const override
1037 {
1038 return new TIntermPreprocessorDirective(*this);
1039 }
1040
1041 private:
1042 PreprocessorDirective mDirective;
1043 ImmutableString mCommand;
1044
1045 TIntermPreprocessorDirective(const TIntermPreprocessorDirective &);
1046 };
1047
EnsureBody(TIntermBlock * body)1048 inline TIntermBlock *TIntermLoop::EnsureBody(TIntermBlock *body)
1049 {
1050 if (ANGLE_LIKELY(body))
1051 {
1052 return body;
1053 }
1054 UNREACHABLE();
1055 return new TIntermBlock();
1056 }
1057
1058 } // namespace sh
1059
1060 #endif // COMPILER_TRANSLATOR_INTERMNODE_H_
1061