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