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