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); ~TIntermAggregate()622 ~TIntermAggregate() override {} 623 624 // Note: only supported for nodes that can be a part of an expression. deepCopy()625 TIntermTyped *deepCopy() const override { return new TIntermAggregate(*this); } 626 627 TIntermAggregate *shallowCopy() const; 628 629 bool hasConstantValue() const override; 630 bool isConstantNullValue() const override; 631 const TConstantUnion *getConstantValue() const override; 632 getAsAggregate()633 TIntermAggregate *getAsAggregate() override { return this; } 634 void traverse(TIntermTraverser *it) final; 635 bool visit(Visit visit, TIntermTraverser *it) final; 636 637 size_t getChildCount() const final; 638 TIntermNode *getChildNode(size_t index) const final; 639 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 640 641 bool hasSideEffects() const override; 642 643 TIntermTyped *fold(TDiagnostics *diagnostics) override; 644 getSequence()645 TIntermSequence *getSequence() override { return &mArguments; } getSequence()646 const TIntermSequence *getSequence() const override { return &mArguments; } 647 setUseEmulatedFunction()648 void setUseEmulatedFunction() { mUseEmulatedFunction = true; } getUseEmulatedFunction()649 bool getUseEmulatedFunction() { return mUseEmulatedFunction; } 650 getFunction()651 const TFunction *getFunction() const { return mFunction; } 652 653 // Get the function name to display to the user in an error message. 654 const char *functionName() const; 655 656 protected: 657 TIntermSequence mArguments; 658 659 // If set to true, replace the built-in function call with an emulated one 660 // to work around driver bugs. Only for calls mapped to ops other than EOpCall*. 661 bool mUseEmulatedFunction; 662 663 const TFunction *const mFunction; 664 665 private: 666 TIntermAggregate(const TFunction *func, 667 const TType &type, 668 TOperator op, 669 TIntermSequence *arguments); 670 671 TIntermAggregate(const TIntermAggregate &node); // note: not deleted, just private! 672 673 void setPrecisionAndQualifier(); 674 TPrecision derivePrecision() const override; 675 void propagatePrecision(TPrecision precision) override; 676 677 bool areChildrenConstQualified(); 678 }; 679 680 // A list of statements. Either the root node which contains declarations and function definitions, 681 // or a block that can be marked with curly braces {}. 682 class TIntermBlock : public TIntermNode, public TIntermAggregateBase 683 { 684 public: TIntermBlock()685 TIntermBlock() : TIntermNode(), mIsTreeRoot(false) {} 686 TIntermBlock(std::initializer_list<TIntermNode *> stmts); ~TIntermBlock()687 ~TIntermBlock() override {} 688 getAsBlock()689 TIntermBlock *getAsBlock() override { return this; } 690 void traverse(TIntermTraverser *it) final; 691 bool visit(Visit visit, TIntermTraverser *it) final; 692 693 size_t getChildCount() const final; 694 TIntermNode *getChildNode(size_t index) const final; 695 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 696 void replaceAllChildren(const TIntermSequence &newStatements); 697 698 // Only intended for initially building the block. 699 void appendStatement(TIntermNode *statement); 700 void insertStatement(size_t insertPosition, TIntermNode *statement); 701 getSequence()702 TIntermSequence *getSequence() override { return &mStatements; } getSequence()703 const TIntermSequence *getSequence() const override { return &mStatements; } 704 deepCopy()705 TIntermBlock *deepCopy() const override { return new TIntermBlock(*this); } 706 setIsTreeRoot()707 void setIsTreeRoot() { mIsTreeRoot = true; } isTreeRoot()708 bool isTreeRoot() const { return mIsTreeRoot; } 709 710 protected: 711 TIntermSequence mStatements; 712 713 // Used to distinguish the tree root from the other blocks. When validating the AST, some 714 // validations are not applicable if not run on the entire tree and are thus skipped. 715 bool mIsTreeRoot; 716 717 private: 718 TIntermBlock(const TIntermBlock &); 719 }; 720 721 // Function prototype. May be in the AST either as a function prototype declaration or as a part of 722 // a function definition. The type of the node is the function return type. 723 class TIntermFunctionPrototype : public TIntermTyped 724 { 725 public: 726 TIntermFunctionPrototype(const TFunction *function); ~TIntermFunctionPrototype()727 ~TIntermFunctionPrototype() override {} 728 getAsFunctionPrototypeNode()729 TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; } 730 void traverse(TIntermTraverser *it) final; 731 bool visit(Visit visit, TIntermTraverser *it) final; 732 733 size_t getChildCount() const final; 734 TIntermNode *getChildNode(size_t index) const final; 735 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 736 737 const TType &getType() const override; 738 deepCopy()739 TIntermTyped *deepCopy() const override 740 { 741 UNREACHABLE(); 742 return nullptr; 743 } hasSideEffects()744 bool hasSideEffects() const override 745 { 746 UNREACHABLE(); 747 return true; 748 } 749 getFunction()750 const TFunction *getFunction() const { return mFunction; } 751 752 protected: 753 const TFunction *const mFunction; 754 }; 755 756 // Node for function definitions. The prototype child node stores the function header including 757 // parameters, and the body child node stores the function body. 758 class TIntermFunctionDefinition : public TIntermNode 759 { 760 public: TIntermFunctionDefinition(TIntermFunctionPrototype * prototype,TIntermBlock * body)761 TIntermFunctionDefinition(TIntermFunctionPrototype *prototype, TIntermBlock *body) 762 : TIntermNode(), mPrototype(prototype), mBody(body) 763 { 764 ASSERT(prototype != nullptr); 765 ASSERT(body != nullptr); 766 } 767 getAsFunctionDefinition()768 TIntermFunctionDefinition *getAsFunctionDefinition() override { return this; } 769 void traverse(TIntermTraverser *it) final; 770 bool visit(Visit visit, TIntermTraverser *it) final; 771 772 size_t getChildCount() const final; 773 TIntermNode *getChildNode(size_t index) const final; 774 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 775 getFunctionPrototype()776 TIntermFunctionPrototype *getFunctionPrototype() const { return mPrototype; } getBody()777 TIntermBlock *getBody() const { return mBody; } 778 getFunction()779 const TFunction *getFunction() const { return mPrototype->getFunction(); } 780 deepCopy()781 TIntermNode *deepCopy() const override 782 { 783 UNREACHABLE(); 784 return nullptr; 785 } 786 787 private: 788 TIntermFunctionPrototype *mPrototype; 789 TIntermBlock *mBody; 790 }; 791 792 // Struct, interface block or variable declaration. Can contain multiple variable declarators. 793 class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase 794 { 795 public: TIntermDeclaration()796 TIntermDeclaration() : TIntermNode() {} 797 TIntermDeclaration(const TVariable *var, TIntermTyped *initExpr); 798 TIntermDeclaration(std::initializer_list<const TVariable *> declarators); 799 TIntermDeclaration(std::initializer_list<TIntermTyped *> declarators); ~TIntermDeclaration()800 ~TIntermDeclaration() override {} 801 getAsDeclarationNode()802 TIntermDeclaration *getAsDeclarationNode() override { return this; } 803 bool visit(Visit visit, TIntermTraverser *it) final; 804 805 size_t getChildCount() const final; 806 TIntermNode *getChildNode(size_t index) const final; 807 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 808 809 // Only intended for initially building the declaration. 810 // The declarator node should be either TIntermSymbol or TIntermBinary with op set to 811 // EOpInitialize. 812 void appendDeclarator(TIntermTyped *declarator); 813 getSequence()814 TIntermSequence *getSequence() override { return &mDeclarators; } getSequence()815 const TIntermSequence *getSequence() const override { return &mDeclarators; } 816 deepCopy()817 TIntermDeclaration *deepCopy() const override 818 { 819 // Note: This is only useful as support for deepCopy of TIntermBlock and TIntermLoop, but is 820 // not sufficient as it will be redeclaring the same TVariable. If a function body is 821 // duplicated for example, it means that both functions reference the same TVariable pointer 822 // which works, but is technically not correct. In particular, maps with TVariable * as key 823 // can get confused. 824 // 825 // After deepCopy() is issued, ReplaceVariables must be used to replace every declared 826 // variable with a duplicate. This is NOT automatically done when deepCopy-ing TIntermBlock 827 // and TIntermLoop nodes. 828 return new TIntermDeclaration(*this); 829 } 830 831 protected: 832 TIntermDeclaration(const TIntermDeclaration &node); 833 834 TIntermSequence mDeclarators; 835 }; 836 837 // Specialized declarations for attributing invariance. 838 class TIntermGlobalQualifierDeclaration : public TIntermNode 839 { 840 public: 841 TIntermGlobalQualifierDeclaration(TIntermSymbol *symbol, 842 bool isPrecise, 843 const TSourceLoc &line); 844 getAsGlobalQualifierDeclarationNode()845 virtual TIntermGlobalQualifierDeclaration *getAsGlobalQualifierDeclarationNode() override 846 { 847 return this; 848 } 849 bool visit(Visit visit, TIntermTraverser *it) final; 850 getSymbol()851 TIntermSymbol *getSymbol() { return mSymbol; } isInvariant()852 bool isInvariant() const { return !mIsPrecise; } isPrecise()853 bool isPrecise() const { return mIsPrecise; } 854 855 size_t getChildCount() const final; 856 TIntermNode *getChildNode(size_t index) const final; 857 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 858 deepCopy()859 TIntermGlobalQualifierDeclaration *deepCopy() const override 860 { 861 return new TIntermGlobalQualifierDeclaration(*this); 862 } 863 864 private: 865 TIntermSymbol *mSymbol; 866 // Either |precise| or |invariant|, determined based on this flag. 867 bool mIsPrecise; 868 869 TIntermGlobalQualifierDeclaration(const TIntermGlobalQualifierDeclaration &); 870 }; 871 872 // For ternary operators like a ? b : c. 873 class TIntermTernary : public TIntermExpression 874 { 875 public: 876 TIntermTernary(TIntermTyped *cond, TIntermTyped *trueExpression, TIntermTyped *falseExpression); 877 getAsTernaryNode()878 TIntermTernary *getAsTernaryNode() override { return this; } 879 bool visit(Visit visit, TIntermTraverser *it) final; 880 881 size_t getChildCount() const final; 882 TIntermNode *getChildNode(size_t index) const final; 883 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 884 getCondition()885 TIntermTyped *getCondition() const { return mCondition; } getTrueExpression()886 TIntermTyped *getTrueExpression() const { return mTrueExpression; } getFalseExpression()887 TIntermTyped *getFalseExpression() const { return mFalseExpression; } 888 deepCopy()889 TIntermTyped *deepCopy() const override { return new TIntermTernary(*this); } 890 hasSideEffects()891 bool hasSideEffects() const override 892 { 893 return mCondition->hasSideEffects() || mTrueExpression->hasSideEffects() || 894 mFalseExpression->hasSideEffects(); 895 } 896 897 TIntermTyped *fold(TDiagnostics *diagnostics) override; 898 899 private: 900 TIntermTernary(const TIntermTernary &node); // Note: not deleted, just private! 901 902 static TQualifier DetermineQualifier(TIntermTyped *cond, 903 TIntermTyped *trueExpression, 904 TIntermTyped *falseExpression); 905 TPrecision derivePrecision() const override; 906 void propagatePrecision(TPrecision precision) override; 907 908 TIntermTyped *mCondition; 909 TIntermTyped *mTrueExpression; 910 TIntermTyped *mFalseExpression; 911 }; 912 913 class TIntermIfElse : public TIntermNode 914 { 915 public: 916 TIntermIfElse(TIntermTyped *cond, TIntermBlock *trueB, TIntermBlock *falseB); 917 getAsIfElseNode()918 TIntermIfElse *getAsIfElseNode() override { return this; } 919 bool visit(Visit visit, TIntermTraverser *it) final; 920 921 size_t getChildCount() const final; 922 TIntermNode *getChildNode(size_t index) const final; 923 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 924 getCondition()925 TIntermTyped *getCondition() const { return mCondition; } getTrueBlock()926 TIntermBlock *getTrueBlock() const { return mTrueBlock; } getFalseBlock()927 TIntermBlock *getFalseBlock() const { return mFalseBlock; } 928 deepCopy()929 TIntermIfElse *deepCopy() const override { return new TIntermIfElse(*this); } 930 931 protected: 932 TIntermTyped *mCondition; 933 TIntermBlock *mTrueBlock; 934 TIntermBlock *mFalseBlock; 935 936 private: 937 TIntermIfElse(const TIntermIfElse &); 938 }; 939 940 // 941 // Switch statement. 942 // 943 class TIntermSwitch : public TIntermNode 944 { 945 public: 946 TIntermSwitch(TIntermTyped *init, TIntermBlock *statementList); 947 getAsSwitchNode()948 TIntermSwitch *getAsSwitchNode() override { return this; } 949 bool visit(Visit visit, TIntermTraverser *it) final; 950 951 size_t getChildCount() const final; 952 TIntermNode *getChildNode(size_t index) const final; 953 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 954 getInit()955 TIntermTyped *getInit() { return mInit; } getStatementList()956 TIntermBlock *getStatementList() { return mStatementList; } 957 958 // Must be called with a non-null statementList. 959 void setStatementList(TIntermBlock *statementList); 960 deepCopy()961 TIntermSwitch *deepCopy() const override { return new TIntermSwitch(*this); } 962 963 protected: 964 TIntermTyped *mInit; 965 TIntermBlock *mStatementList; 966 967 private: 968 TIntermSwitch(const TIntermSwitch &); 969 }; 970 971 // 972 // Case label. 973 // 974 class TIntermCase : public TIntermNode 975 { 976 public: TIntermCase(TIntermTyped * condition)977 TIntermCase(TIntermTyped *condition) : TIntermNode(), mCondition(condition) {} 978 getAsCaseNode()979 TIntermCase *getAsCaseNode() override { return this; } 980 bool visit(Visit visit, TIntermTraverser *it) final; 981 982 size_t getChildCount() const final; 983 TIntermNode *getChildNode(size_t index) const final; 984 bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override; 985 hasCondition()986 bool hasCondition() const { return mCondition != nullptr; } getCondition()987 TIntermTyped *getCondition() const { return mCondition; } 988 deepCopy()989 TIntermCase *deepCopy() const override { return new TIntermCase(*this); } 990 991 protected: 992 TIntermTyped *mCondition; 993 994 private: 995 TIntermCase(const TIntermCase &); 996 }; 997 998 // 999 // Preprocessor Directive. 1000 // #ifdef, #define, #if, #endif, etc. 1001 // 1002 1003 enum class PreprocessorDirective 1004 { 1005 Define, 1006 Ifdef, 1007 If, 1008 Endif, 1009 }; 1010 1011 class TIntermPreprocessorDirective final : public TIntermNode 1012 { 1013 public: 1014 // This could also take an ImmutableString as an argument. 1015 TIntermPreprocessorDirective(PreprocessorDirective directive, ImmutableString command); 1016 ~TIntermPreprocessorDirective() final; 1017 1018 void traverse(TIntermTraverser *it) final; 1019 bool visit(Visit visit, TIntermTraverser *it) final; replaceChildNode(TIntermNode *,TIntermNode *)1020 bool replaceChildNode(TIntermNode *, TIntermNode *) final { return false; } 1021 getAsPreprocessorDirective()1022 TIntermPreprocessorDirective *getAsPreprocessorDirective() final { return this; } 1023 size_t getChildCount() const final; 1024 TIntermNode *getChildNode(size_t index) const final; 1025 getDirective()1026 PreprocessorDirective getDirective() const { return mDirective; } getCommand()1027 const ImmutableString &getCommand() const { return mCommand; } 1028 deepCopy()1029 TIntermPreprocessorDirective *deepCopy() const override 1030 { 1031 return new TIntermPreprocessorDirective(*this); 1032 } 1033 1034 private: 1035 PreprocessorDirective mDirective; 1036 ImmutableString mCommand; 1037 1038 TIntermPreprocessorDirective(const TIntermPreprocessorDirective &); 1039 }; 1040 1041 } // namespace sh 1042 1043 #endif // COMPILER_TRANSLATOR_INTERMNODE_H_ 1044