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