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