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