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