1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // 16 // Definition of the in-memory high-level intermediate representation 17 // of shaders. This is a tree that parser creates. 18 // 19 // Nodes in the tree are defined as a hierarchy of classes derived from 20 // TIntermNode. Each is a node in a tree. There is no preset branching factor; 21 // each node can have it's own type of list of children. 22 // 23 24 #ifndef __INTERMEDIATE_H 25 #define __INTERMEDIATE_H 26 27 #include "Common.h" 28 #include "Types.h" 29 #include "ConstantUnion.h" 30 31 // 32 // Operators used by the high-level (parse tree) representation. 33 // 34 enum TOperator { 35 EOpNull, // if in a node, should only mean a node is still being built 36 EOpSequence, // denotes a list of statements, or parameters, etc. 37 EOpFunctionCall, 38 EOpFunction, // For function definition 39 EOpParameters, // an aggregate listing the parameters to a function 40 41 EOpDeclaration, 42 EOpInvariantDeclaration, // Specialized declarations for attributing invariance 43 EOpPrototype, 44 45 // 46 // Unary operators 47 // 48 49 EOpNegative, 50 EOpLogicalNot, 51 EOpVectorLogicalNot, 52 EOpBitwiseNot, 53 54 EOpPostIncrement, 55 EOpPostDecrement, 56 EOpPreIncrement, 57 EOpPreDecrement, 58 59 // 60 // binary operations 61 // 62 63 EOpAdd, 64 EOpSub, 65 EOpMul, 66 EOpDiv, 67 EOpEqual, 68 EOpNotEqual, 69 EOpVectorEqual, 70 EOpVectorNotEqual, 71 EOpLessThan, 72 EOpGreaterThan, 73 EOpLessThanEqual, 74 EOpGreaterThanEqual, 75 EOpComma, 76 77 EOpOuterProduct, 78 EOpTranspose, 79 EOpDeterminant, 80 EOpInverse, 81 82 EOpVectorTimesScalar, 83 EOpVectorTimesMatrix, 84 EOpMatrixTimesVector, 85 EOpMatrixTimesScalar, 86 87 EOpLogicalOr, 88 EOpLogicalXor, 89 EOpLogicalAnd, 90 91 EOpIMod, 92 EOpBitShiftLeft, 93 EOpBitShiftRight, 94 EOpBitwiseAnd, 95 EOpBitwiseXor, 96 EOpBitwiseOr, 97 98 EOpIndexDirect, 99 EOpIndexIndirect, 100 EOpIndexDirectStruct, 101 EOpIndexDirectInterfaceBlock, 102 103 EOpVectorSwizzle, 104 105 // 106 // Built-in functions potentially mapped to operators 107 // 108 109 EOpRadians, 110 EOpDegrees, 111 EOpSin, 112 EOpCos, 113 EOpTan, 114 EOpAsin, 115 EOpAcos, 116 EOpAtan, 117 EOpSinh, 118 EOpCosh, 119 EOpTanh, 120 EOpAsinh, 121 EOpAcosh, 122 EOpAtanh, 123 124 EOpPow, 125 EOpExp, 126 EOpLog, 127 EOpExp2, 128 EOpLog2, 129 EOpSqrt, 130 EOpInverseSqrt, 131 132 EOpAbs, 133 EOpSign, 134 EOpFloor, 135 EOpTrunc, 136 EOpRound, 137 EOpRoundEven, 138 EOpCeil, 139 EOpFract, 140 EOpMod, 141 EOpModf, 142 EOpMin, 143 EOpMax, 144 EOpClamp, 145 EOpMix, 146 EOpStep, 147 EOpSmoothStep, 148 EOpIsNan, 149 EOpIsInf, 150 EOpFloatBitsToInt, 151 EOpFloatBitsToUint, 152 EOpIntBitsToFloat, 153 EOpUintBitsToFloat, 154 EOpPackSnorm2x16, 155 EOpPackUnorm2x16, 156 EOpPackHalf2x16, 157 EOpUnpackSnorm2x16, 158 EOpUnpackUnorm2x16, 159 EOpUnpackHalf2x16, 160 161 EOpLength, 162 EOpDistance, 163 EOpDot, 164 EOpCross, 165 EOpNormalize, 166 EOpFaceForward, 167 EOpReflect, 168 EOpRefract, 169 170 EOpDFdx, // Fragment only, OES_standard_derivatives extension 171 EOpDFdy, // Fragment only, OES_standard_derivatives extension 172 EOpFwidth, // Fragment only, OES_standard_derivatives extension 173 174 EOpMatrixTimesMatrix, 175 176 EOpAny, 177 EOpAll, 178 179 // 180 // Branch 181 // 182 183 EOpKill, // Fragment only 184 EOpReturn, 185 EOpBreak, 186 EOpContinue, 187 188 // 189 // Constructors 190 // 191 192 EOpConstructInt, 193 EOpConstructUInt, 194 EOpConstructBool, 195 EOpConstructFloat, 196 EOpConstructVec2, 197 EOpConstructVec3, 198 EOpConstructVec4, 199 EOpConstructBVec2, 200 EOpConstructBVec3, 201 EOpConstructBVec4, 202 EOpConstructIVec2, 203 EOpConstructIVec3, 204 EOpConstructIVec4, 205 EOpConstructUVec2, 206 EOpConstructUVec3, 207 EOpConstructUVec4, 208 EOpConstructMat2, 209 EOpConstructMat2x3, 210 EOpConstructMat2x4, 211 EOpConstructMat3x2, 212 EOpConstructMat3, 213 EOpConstructMat3x4, 214 EOpConstructMat4x2, 215 EOpConstructMat4x3, 216 EOpConstructMat4, 217 EOpConstructStruct, 218 219 // 220 // moves 221 // 222 223 EOpAssign, 224 EOpInitialize, 225 EOpAddAssign, 226 EOpSubAssign, 227 EOpMulAssign, 228 EOpVectorTimesMatrixAssign, 229 EOpVectorTimesScalarAssign, 230 EOpMatrixTimesScalarAssign, 231 EOpMatrixTimesMatrixAssign, 232 EOpDivAssign, 233 EOpIModAssign, 234 EOpBitShiftLeftAssign, 235 EOpBitShiftRightAssign, 236 EOpBitwiseAndAssign, 237 EOpBitwiseXorAssign, 238 EOpBitwiseOrAssign 239 }; 240 241 extern TOperator TypeToConstructorOperator(const TType &type); 242 extern const char* getOperatorString(TOperator op); 243 244 class TIntermTraverser; 245 class TIntermAggregate; 246 class TIntermBinary; 247 class TIntermUnary; 248 class TIntermConstantUnion; 249 class TIntermSelection; 250 class TIntermTyped; 251 class TIntermSymbol; 252 class TIntermLoop; 253 class TIntermBranch; 254 class TInfoSink; 255 class TIntermSwitch; 256 class TIntermCase; 257 258 // 259 // Base class for the tree nodes 260 // 261 class TIntermNode { 262 public: 263 POOL_ALLOCATOR_NEW_DELETE(); 264 TIntermNode()265 TIntermNode() 266 { 267 // TODO: Move this to TSourceLoc constructor 268 // after getting rid of TPublicType. 269 line.first_file = line.last_file = 0; 270 line.first_line = line.last_line = 0; 271 } 272 getLine()273 const TSourceLoc& getLine() const { return line; } setLine(const TSourceLoc & l)274 void setLine(const TSourceLoc& l) { line = l; } 275 276 virtual void traverse(TIntermTraverser*) = 0; getAsTyped()277 virtual TIntermTyped* getAsTyped() { return 0; } getAsConstantUnion()278 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } getAsAggregate()279 virtual TIntermAggregate* getAsAggregate() { return 0; } getAsBinaryNode()280 virtual TIntermBinary* getAsBinaryNode() { return 0; } getAsUnaryNode()281 virtual TIntermUnary* getAsUnaryNode() { return 0; } getAsSelectionNode()282 virtual TIntermSelection* getAsSelectionNode() { return 0; } getAsSymbolNode()283 virtual TIntermSymbol* getAsSymbolNode() { return 0; } getAsLoopNode()284 virtual TIntermLoop* getAsLoopNode() { return 0; } getAsBranchNode()285 virtual TIntermBranch* getAsBranchNode() { return 0; } getAsSwitchNode()286 virtual TIntermSwitch *getAsSwitchNode() { return 0; } getAsCaseNode()287 virtual TIntermCase *getAsCaseNode() { return 0; } ~TIntermNode()288 virtual ~TIntermNode() { } 289 290 protected: 291 TSourceLoc line; 292 }; 293 294 // 295 // This is just to help yacc. 296 // 297 struct TIntermNodePair { 298 TIntermNode* node1; 299 TIntermNode* node2; 300 }; 301 302 // 303 // Intermediate class for nodes that have a type. 304 // 305 class TIntermTyped : public TIntermNode { 306 public: TIntermTyped(const TType & t)307 TIntermTyped(const TType& t) : type(t) { } getAsTyped()308 virtual TIntermTyped* getAsTyped() { return this; } 309 setType(const TType & t)310 virtual void setType(const TType& t) { type = t; } getType()311 const TType& getType() const { return type; } getTypePointer()312 TType* getTypePointer() { return &type; } 313 getBasicType()314 TBasicType getBasicType() const { return type.getBasicType(); } getQualifier()315 TQualifier getQualifier() const { return type.getQualifier(); } getPrecision()316 TPrecision getPrecision() const { return type.getPrecision(); } getNominalSize()317 int getNominalSize() const { return type.getNominalSize(); } getSecondarySize()318 int getSecondarySize() const { return type.getSecondarySize(); } 319 isInterfaceBlock()320 bool isInterfaceBlock() const { return type.isInterfaceBlock(); } isMatrix()321 bool isMatrix() const { return type.isMatrix(); } isArray()322 bool isArray() const { return type.isArray(); } isVector()323 bool isVector() const { return type.isVector(); } isScalar()324 bool isScalar() const { return type.isScalar(); } isScalarInt()325 bool isScalarInt() const { return type.isScalarInt(); } isRegister()326 bool isRegister() const { return type.isRegister(); } // Fits in a 4-element register isStruct()327 bool isStruct() const { return type.isStruct(); } getBasicString()328 const char* getBasicString() const { return type.getBasicString(); } getQualifierString()329 const char* getQualifierString() const { return type.getQualifierString(); } getCompleteString()330 TString getCompleteString() const { return type.getCompleteString(); } 331 totalRegisterCount()332 int totalRegisterCount() const { return type.totalRegisterCount(); } blockRegisterCount(bool samplersOnly)333 int blockRegisterCount(bool samplersOnly) const { return samplersOnly ? type.totalSamplerRegisterCount() : type.blockRegisterCount(); } elementRegisterCount()334 int elementRegisterCount() const { return type.elementRegisterCount(); } registerSize()335 int registerSize() const { return type.registerSize(); } getArraySize()336 int getArraySize() const { return type.getArraySize(); } 337 338 static TIntermTyped *CreateIndexNode(int index); 339 protected: 340 TType type; 341 }; 342 343 // 344 // Handle for, do-while, and while loops. 345 // 346 enum TLoopType { 347 ELoopFor, 348 ELoopWhile, 349 ELoopDoWhile 350 }; 351 352 class TIntermLoop : public TIntermNode { 353 public: TIntermLoop(TLoopType aType,TIntermNode * aInit,TIntermTyped * aCond,TIntermTyped * aExpr,TIntermNode * aBody)354 TIntermLoop(TLoopType aType, 355 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, 356 TIntermNode* aBody) : 357 type(aType), 358 init(aInit), 359 cond(aCond), 360 expr(aExpr), 361 body(aBody), 362 unrollFlag(false) { } 363 getAsLoopNode()364 virtual TIntermLoop* getAsLoopNode() { return this; } 365 virtual void traverse(TIntermTraverser*); 366 getType()367 TLoopType getType() const { return type; } getInit()368 TIntermNode* getInit() { return init; } getCondition()369 TIntermTyped* getCondition() { return cond; } getExpression()370 TIntermTyped* getExpression() { return expr; } getBody()371 TIntermNode* getBody() { return body; } 372 setUnrollFlag(bool flag)373 void setUnrollFlag(bool flag) { unrollFlag = flag; } getUnrollFlag()374 bool getUnrollFlag() { return unrollFlag; } 375 376 protected: 377 TLoopType type; 378 TIntermNode* init; // for-loop initialization 379 TIntermTyped* cond; // loop exit condition 380 TIntermTyped* expr; // for-loop expression 381 TIntermNode* body; // loop body 382 383 bool unrollFlag; // Whether the loop should be unrolled or not. 384 }; 385 386 // 387 // Handle break, continue, return, and kill. 388 // 389 class TIntermBranch : public TIntermNode { 390 public: TIntermBranch(TOperator op,TIntermTyped * e)391 TIntermBranch(TOperator op, TIntermTyped* e) : 392 flowOp(op), 393 expression(e) { } 394 getAsBranchNode()395 virtual TIntermBranch* getAsBranchNode() { return this; } 396 virtual void traverse(TIntermTraverser*); 397 getFlowOp()398 TOperator getFlowOp() { return flowOp; } getExpression()399 TIntermTyped* getExpression() { return expression; } 400 401 protected: 402 TOperator flowOp; 403 TIntermTyped* expression; // non-zero except for "return exp;" statements 404 }; 405 406 // 407 // Nodes that correspond to symbols or constants in the source code. 408 // 409 class TIntermSymbol : public TIntermTyped { 410 public: 411 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from 412 // per process globalpoolallocator, then it causes increased memory usage per compile 413 // it is essential to use "symbol = sym" to assign to symbol TIntermSymbol(int i,const TString & sym,const TType & t)414 TIntermSymbol(int i, const TString& sym, const TType& t) : 415 TIntermTyped(t), id(i) { symbol = sym; } 416 getId()417 int getId() const { return id; } getSymbol()418 const TString& getSymbol() const { return symbol; } 419 setId(int newId)420 void setId(int newId) { id = newId; } 421 422 virtual void traverse(TIntermTraverser*); getAsSymbolNode()423 virtual TIntermSymbol* getAsSymbolNode() { return this; } 424 425 protected: 426 int id; 427 TString symbol; 428 }; 429 430 class TIntermConstantUnion : public TIntermTyped { 431 public: TIntermConstantUnion(ConstantUnion * unionPointer,const TType & t)432 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) 433 { 434 getTypePointer()->setQualifier(EvqConstExpr); 435 } 436 getUnionArrayPointer()437 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } 438 getIConst(int index)439 int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } getUConst(int index)440 int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; } getFConst(int index)441 float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } getBConst(int index)442 bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } 443 444 // Previous union pointer freed on pool deallocation. replaceConstantUnion(ConstantUnion * safeConstantUnion)445 void replaceConstantUnion(ConstantUnion *safeConstantUnion) { unionArrayPointer = safeConstantUnion; } 446 getAsConstantUnion()447 virtual TIntermConstantUnion* getAsConstantUnion() { return this; } 448 virtual void traverse(TIntermTraverser*); 449 450 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); 451 452 protected: 453 ConstantUnion *unionArrayPointer; 454 }; 455 456 // 457 // Intermediate class for node types that hold operators. 458 // 459 class TIntermOperator : public TIntermTyped { 460 public: getOp()461 TOperator getOp() const { return op; } setOp(TOperator o)462 void setOp(TOperator o) { op = o; } 463 464 bool modifiesState() const; 465 bool isConstructor() const; 466 467 protected: TIntermOperator(TOperator o)468 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} TIntermOperator(TOperator o,TType & t)469 TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} 470 TOperator op; 471 }; 472 473 // 474 // Nodes for all the basic binary math operators. 475 // 476 class TIntermBinary : public TIntermOperator { 477 public: TIntermBinary(TOperator o)478 TIntermBinary(TOperator o) : TIntermOperator(o) {} 479 getAsBinaryNode()480 TIntermBinary* getAsBinaryNode() override { return this; } 481 void traverse(TIntermTraverser*) override; 482 setType(const TType & t)483 void setType(const TType &t) override 484 { 485 type = t; 486 487 if(left->getQualifier() == EvqConstExpr && right->getQualifier() == EvqConstExpr) 488 { 489 type.setQualifier(EvqConstExpr); 490 } 491 } 492 setLeft(TIntermTyped * n)493 void setLeft(TIntermTyped* n) { left = n; } setRight(TIntermTyped * n)494 void setRight(TIntermTyped* n) { right = n; } getLeft()495 TIntermTyped* getLeft() const { return left; } getRight()496 TIntermTyped* getRight() const { return right; } 497 bool promote(TInfoSink&); 498 499 protected: 500 TIntermTyped* left; 501 TIntermTyped* right; 502 }; 503 504 // 505 // Nodes for unary math operators. 506 // 507 class TIntermUnary : public TIntermOperator { 508 public: TIntermUnary(TOperator o,TType & t)509 TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} TIntermUnary(TOperator o)510 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} 511 setType(const TType & t)512 void setType(const TType &t) override 513 { 514 type = t; 515 516 if(operand->getQualifier() == EvqConstExpr) 517 { 518 type.setQualifier(EvqConstExpr); 519 } 520 } 521 522 void traverse(TIntermTraverser*) override; getAsUnaryNode()523 TIntermUnary* getAsUnaryNode() override { return this; } 524 setOperand(TIntermTyped * o)525 void setOperand(TIntermTyped* o) { operand = o; } getOperand()526 TIntermTyped* getOperand() { return operand; } 527 bool promote(TInfoSink&, const TType *funcReturnType); 528 529 protected: 530 TIntermTyped* operand; 531 }; 532 533 typedef TVector<TIntermNode*> TIntermSequence; 534 typedef TVector<int> TQualifierList; 535 536 // 537 // Nodes that operate on an arbitrary sized set of children. 538 // 539 class TIntermAggregate : public TIntermOperator { 540 public: TIntermAggregate()541 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; } TIntermAggregate(TOperator o)542 TIntermAggregate(TOperator o) : TIntermOperator(o), userDefined(false) { endLine = { 0, 0, 0, 0 }; } ~TIntermAggregate()543 ~TIntermAggregate() { } 544 getAsAggregate()545 TIntermAggregate* getAsAggregate() override { return this; } 546 void traverse(TIntermTraverser*) override; 547 getSequence()548 TIntermSequence& getSequence() { return sequence; } 549 setType(const TType & t)550 void setType(const TType &t) override 551 { 552 type = t; 553 554 if(op != EOpFunctionCall) 555 { 556 for(TIntermNode *node : sequence) 557 { 558 if(!node->getAsTyped() || node->getAsTyped()->getQualifier() != EvqConstExpr) 559 { 560 return; 561 } 562 } 563 564 type.setQualifier(EvqConstExpr); 565 } 566 } 567 setName(const TString & n)568 void setName(const TString& n) { name = n; } getName()569 const TString& getName() const { return name; } 570 setUserDefined()571 void setUserDefined() { userDefined = true; } isUserDefined()572 bool isUserDefined() const { return userDefined; } 573 setOptimize(bool o)574 void setOptimize(bool o) { optimize = o; } getOptimize()575 bool getOptimize() { return optimize; } setDebug(bool d)576 void setDebug(bool d) { debug = d; } getDebug()577 bool getDebug() { return debug; } 578 setEndLine(const TSourceLoc & line)579 void setEndLine(const TSourceLoc& line) { endLine = line; } getEndLine()580 const TSourceLoc& getEndLine() const { return endLine; } 581 isConstantFoldable()582 bool isConstantFoldable() 583 { 584 for(TIntermNode *node : sequence) 585 { 586 if(!node->getAsConstantUnion() || !node->getAsConstantUnion()->getUnionArrayPointer()) 587 { 588 return false; 589 } 590 } 591 592 return true; 593 } 594 595 protected: 596 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor 597 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator 598 TIntermSequence sequence; 599 TString name; 600 bool userDefined; // used for user defined function names 601 602 bool optimize; 603 bool debug; 604 TSourceLoc endLine; 605 }; 606 607 // 608 // For if tests. Simplified since there is no switch statement. 609 // 610 class TIntermSelection : public TIntermTyped { 611 public: TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB)612 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : 613 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB,const TType & type)614 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : 615 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) 616 { 617 this->type.setQualifier(EvqTemporary); 618 } 619 620 virtual void traverse(TIntermTraverser*); 621 usesTernaryOperator()622 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } getCondition()623 TIntermTyped* getCondition() const { return condition; } getTrueBlock()624 TIntermNode* getTrueBlock() const { return trueBlock; } getFalseBlock()625 TIntermNode* getFalseBlock() const { return falseBlock; } getAsSelectionNode()626 TIntermSelection* getAsSelectionNode() { return this; } 627 628 protected: 629 TIntermTyped* condition; 630 TIntermNode* trueBlock; 631 TIntermNode* falseBlock; 632 }; 633 634 // 635 // Switch statement. 636 // 637 class TIntermSwitch : public TIntermNode 638 { 639 public: TIntermSwitch(TIntermTyped * init,TIntermAggregate * statementList)640 TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList) 641 : TIntermNode(), mInit(init), mStatementList(statementList) 642 {} 643 644 void traverse(TIntermTraverser *it); 645 getAsSwitchNode()646 TIntermSwitch *getAsSwitchNode() { return this; } 647 getInit()648 TIntermTyped *getInit() { return mInit; } getStatementList()649 TIntermAggregate *getStatementList() { return mStatementList; } setStatementList(TIntermAggregate * statementList)650 void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; } 651 652 protected: 653 TIntermTyped *mInit; 654 TIntermAggregate *mStatementList; 655 }; 656 657 // 658 // Case label. 659 // 660 class TIntermCase : public TIntermNode 661 { 662 public: TIntermCase(TIntermTyped * condition)663 TIntermCase(TIntermTyped *condition) 664 : TIntermNode(), mCondition(condition) 665 {} 666 667 void traverse(TIntermTraverser *it); 668 getAsCaseNode()669 TIntermCase *getAsCaseNode() { return this; } 670 hasCondition()671 bool hasCondition() const { return mCondition != nullptr; } getCondition()672 TIntermTyped *getCondition() const { return mCondition; } 673 674 protected: 675 TIntermTyped *mCondition; 676 }; 677 678 enum Visit 679 { 680 PreVisit, 681 InVisit, 682 PostVisit 683 }; 684 685 // 686 // For traversing the tree. User should derive from this, 687 // put their traversal specific data in it, and then pass 688 // it to a Traverse method. 689 // 690 // When using this, just fill in the methods for nodes you want visited. 691 // Return false from a pre-visit to skip visiting that node's subtree. 692 // 693 class TIntermTraverser 694 { 695 public: 696 POOL_ALLOCATOR_NEW_DELETE(); 697 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : preVisit(preVisit)698 preVisit(preVisit), 699 inVisit(inVisit), 700 postVisit(postVisit), 701 rightToLeft(rightToLeft), 702 mDepth(0) {} ~TIntermTraverser()703 virtual ~TIntermTraverser() {}; 704 visitSymbol(TIntermSymbol *)705 virtual void visitSymbol(TIntermSymbol*) {} visitConstantUnion(TIntermConstantUnion *)706 virtual void visitConstantUnion(TIntermConstantUnion*) {} visitBinary(Visit visit,TIntermBinary *)707 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} visitUnary(Visit visit,TIntermUnary *)708 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} visitSelection(Visit visit,TIntermSelection *)709 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} visitAggregate(Visit visit,TIntermAggregate *)710 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} visitLoop(Visit visit,TIntermLoop *)711 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} visitBranch(Visit visit,TIntermBranch *)712 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} visitSwitch(Visit,TIntermSwitch *)713 virtual bool visitSwitch(Visit, TIntermSwitch*) { return true; } visitCase(Visit,TIntermCase *)714 virtual bool visitCase(Visit, TIntermCase*) { return true; } 715 incrementDepth(TIntermNode * current)716 void incrementDepth(TIntermNode *current) 717 { 718 mDepth++; 719 mPath.push_back(current); 720 } 721 decrementDepth()722 void decrementDepth() 723 { 724 mDepth--; 725 mPath.pop_back(); 726 } 727 getParentNode()728 TIntermNode *getParentNode() 729 { 730 return mPath.size() == 0 ? nullptr : mPath.back(); 731 } 732 733 const bool preVisit; 734 const bool inVisit; 735 const bool postVisit; 736 const bool rightToLeft; 737 738 protected: 739 int mDepth; 740 741 // All the nodes from root to the current node's parent during traversing. 742 TVector<TIntermNode *> mPath; 743 744 private: 745 struct ParentBlock 746 { ParentBlockParentBlock747 ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn) 748 : node(nodeIn), pos(posIn) 749 {} 750 751 TIntermAggregate *node; 752 TIntermSequence::size_type pos; 753 }; 754 // All the code blocks from the root to the current node's parent during traversal. 755 std::vector<ParentBlock> mParentBlockStack; 756 }; 757 758 #endif // __INTERMEDIATE_H 759