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 const char* getOperatorString(TOperator op); 242 243 class TIntermTraverser; 244 class TIntermAggregate; 245 class TIntermBinary; 246 class TIntermUnary; 247 class TIntermConstantUnion; 248 class TIntermSelection; 249 class TIntermTyped; 250 class TIntermSymbol; 251 class TIntermLoop; 252 class TIntermBranch; 253 class TInfoSink; 254 class TIntermSwitch; 255 class TIntermCase; 256 257 // 258 // Base class for the tree nodes 259 // 260 class TIntermNode { 261 public: 262 POOL_ALLOCATOR_NEW_DELETE(); 263 TIntermNode()264 TIntermNode() 265 { 266 // TODO: Move this to TSourceLoc constructor 267 // after getting rid of TPublicType. 268 line.first_file = line.last_file = 0; 269 line.first_line = line.last_line = 0; 270 } 271 getLine()272 const TSourceLoc& getLine() const { return line; } setLine(const TSourceLoc & l)273 void setLine(const TSourceLoc& l) { line = l; } 274 275 virtual void traverse(TIntermTraverser*) = 0; getAsTyped()276 virtual TIntermTyped* getAsTyped() { return 0; } getAsConstantUnion()277 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; } getAsAggregate()278 virtual TIntermAggregate* getAsAggregate() { return 0; } getAsBinaryNode()279 virtual TIntermBinary* getAsBinaryNode() { return 0; } getAsUnaryNode()280 virtual TIntermUnary* getAsUnaryNode() { return 0; } getAsSelectionNode()281 virtual TIntermSelection* getAsSelectionNode() { return 0; } getAsSymbolNode()282 virtual TIntermSymbol* getAsSymbolNode() { return 0; } getAsLoopNode()283 virtual TIntermLoop* getAsLoopNode() { return 0; } getAsBranchNode()284 virtual TIntermBranch* getAsBranchNode() { return 0; } getAsSwitchNode()285 virtual TIntermSwitch *getAsSwitchNode() { return 0; } getAsCaseNode()286 virtual TIntermCase *getAsCaseNode() { return 0; } ~TIntermNode()287 virtual ~TIntermNode() { } 288 289 protected: 290 TSourceLoc line; 291 }; 292 293 // 294 // This is just to help yacc. 295 // 296 struct TIntermNodePair { 297 TIntermNode* node1; 298 TIntermNode* node2; 299 }; 300 301 // 302 // Intermediate class for nodes that have a type. 303 // 304 class TIntermTyped : public TIntermNode { 305 public: TIntermTyped(const TType & t)306 TIntermTyped(const TType& t) : type(t) { } getAsTyped()307 virtual TIntermTyped* getAsTyped() { return this; } 308 setType(const TType & t)309 virtual void setType(const TType& t) { type = t; } getType()310 const TType& getType() const { return type; } getTypePointer()311 TType* getTypePointer() { return &type; } 312 getBasicType()313 TBasicType getBasicType() const { return type.getBasicType(); } getQualifier()314 TQualifier getQualifier() const { return type.getQualifier(); } getPrecision()315 TPrecision getPrecision() const { return type.getPrecision(); } getNominalSize()316 int getNominalSize() const { return type.getNominalSize(); } getSecondarySize()317 int getSecondarySize() const { return type.getSecondarySize(); } 318 isInterfaceBlock()319 bool isInterfaceBlock() const { return type.isInterfaceBlock(); } isMatrix()320 bool isMatrix() const { return type.isMatrix(); } isArray()321 bool isArray() const { return type.isArray(); } isVector()322 bool isVector() const { return type.isVector(); } isScalar()323 bool isScalar() const { return type.isScalar(); } isScalarInt()324 bool isScalarInt() const { return type.isScalarInt(); } isRegister()325 bool isRegister() const { return type.isRegister(); } // Fits in a 4-element register isStruct()326 bool isStruct() const { return type.isStruct(); } getBasicString()327 const char* getBasicString() const { return type.getBasicString(); } getQualifierString()328 const char* getQualifierString() const { return type.getQualifierString(); } getCompleteString()329 TString getCompleteString() const { return type.getCompleteString(); } 330 totalRegisterCount()331 int totalRegisterCount() const { return type.totalRegisterCount(); } blockRegisterCount()332 int blockRegisterCount() const { return type.blockRegisterCount(); } elementRegisterCount()333 int elementRegisterCount() const { return type.elementRegisterCount(); } registerSize()334 int registerSize() const { return type.registerSize(); } getArraySize()335 int getArraySize() const { return type.getArraySize(); } 336 337 protected: 338 TType type; 339 }; 340 341 // 342 // Handle for, do-while, and while loops. 343 // 344 enum TLoopType { 345 ELoopFor, 346 ELoopWhile, 347 ELoopDoWhile 348 }; 349 350 class TIntermLoop : public TIntermNode { 351 public: TIntermLoop(TLoopType aType,TIntermNode * aInit,TIntermTyped * aCond,TIntermTyped * aExpr,TIntermNode * aBody)352 TIntermLoop(TLoopType aType, 353 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, 354 TIntermNode* aBody) : 355 type(aType), 356 init(aInit), 357 cond(aCond), 358 expr(aExpr), 359 body(aBody), 360 unrollFlag(false) { } 361 getAsLoopNode()362 virtual TIntermLoop* getAsLoopNode() { return this; } 363 virtual void traverse(TIntermTraverser*); 364 getType()365 TLoopType getType() const { return type; } getInit()366 TIntermNode* getInit() { return init; } getCondition()367 TIntermTyped* getCondition() { return cond; } getExpression()368 TIntermTyped* getExpression() { return expr; } getBody()369 TIntermNode* getBody() { return body; } 370 setUnrollFlag(bool flag)371 void setUnrollFlag(bool flag) { unrollFlag = flag; } getUnrollFlag()372 bool getUnrollFlag() { return unrollFlag; } 373 374 protected: 375 TLoopType type; 376 TIntermNode* init; // for-loop initialization 377 TIntermTyped* cond; // loop exit condition 378 TIntermTyped* expr; // for-loop expression 379 TIntermNode* body; // loop body 380 381 bool unrollFlag; // Whether the loop should be unrolled or not. 382 }; 383 384 // 385 // Handle break, continue, return, and kill. 386 // 387 class TIntermBranch : public TIntermNode { 388 public: TIntermBranch(TOperator op,TIntermTyped * e)389 TIntermBranch(TOperator op, TIntermTyped* e) : 390 flowOp(op), 391 expression(e) { } 392 getAsBranchNode()393 virtual TIntermBranch* getAsBranchNode() { return this; } 394 virtual void traverse(TIntermTraverser*); 395 getFlowOp()396 TOperator getFlowOp() { return flowOp; } getExpression()397 TIntermTyped* getExpression() { return expression; } 398 399 protected: 400 TOperator flowOp; 401 TIntermTyped* expression; // non-zero except for "return exp;" statements 402 }; 403 404 // 405 // Nodes that correspond to symbols or constants in the source code. 406 // 407 class TIntermSymbol : public TIntermTyped { 408 public: 409 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from 410 // per process globalpoolallocator, then it causes increased memory usage per compile 411 // it is essential to use "symbol = sym" to assign to symbol TIntermSymbol(int i,const TString & sym,const TType & t)412 TIntermSymbol(int i, const TString& sym, const TType& t) : 413 TIntermTyped(t), id(i) { symbol = sym; } 414 getId()415 int getId() const { return id; } getSymbol()416 const TString& getSymbol() const { return symbol; } 417 setId(int newId)418 void setId(int newId) { id = newId; } 419 420 virtual void traverse(TIntermTraverser*); getAsSymbolNode()421 virtual TIntermSymbol* getAsSymbolNode() { return this; } 422 423 protected: 424 int id; 425 TString symbol; 426 }; 427 428 class TIntermConstantUnion : public TIntermTyped { 429 public: TIntermConstantUnion(ConstantUnion * unionPointer,const TType & t)430 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) 431 { 432 getTypePointer()->setQualifier(EvqConstExpr); 433 } 434 getUnionArrayPointer()435 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; } 436 getIConst(int index)437 int getIConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } getUConst(int index)438 int getUConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; } getFConst(int index)439 float getFConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } getBConst(int index)440 bool getBConst(int index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } 441 442 // Previous union pointer freed on pool deallocation. replaceConstantUnion(ConstantUnion * safeConstantUnion)443 void replaceConstantUnion(ConstantUnion *safeConstantUnion) { unionArrayPointer = safeConstantUnion; } 444 getAsConstantUnion()445 virtual TIntermConstantUnion* getAsConstantUnion() { return this; } 446 virtual void traverse(TIntermTraverser*); 447 448 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&); 449 450 protected: 451 ConstantUnion *unionArrayPointer; 452 }; 453 454 // 455 // Intermediate class for node types that hold operators. 456 // 457 class TIntermOperator : public TIntermTyped { 458 public: getOp()459 TOperator getOp() const { return op; } setOp(TOperator o)460 void setOp(TOperator o) { op = o; } 461 462 bool modifiesState() const; 463 bool isConstructor() const; 464 465 protected: TIntermOperator(TOperator o)466 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} TIntermOperator(TOperator o,TType & t)467 TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} 468 TOperator op; 469 }; 470 471 // 472 // Nodes for all the basic binary math operators. 473 // 474 class TIntermBinary : public TIntermOperator { 475 public: TIntermBinary(TOperator o)476 TIntermBinary(TOperator o) : TIntermOperator(o) {} 477 getAsBinaryNode()478 virtual TIntermBinary* getAsBinaryNode() { return this; } 479 virtual void traverse(TIntermTraverser*); 480 setType(const TType & t)481 void setType(const TType &t) override 482 { 483 type = t; 484 485 if(left->getQualifier() == EvqConstExpr && right->getQualifier() == EvqConstExpr) 486 { 487 type.setQualifier(EvqConstExpr); 488 } 489 } 490 setLeft(TIntermTyped * n)491 void setLeft(TIntermTyped* n) { left = n; } setRight(TIntermTyped * n)492 void setRight(TIntermTyped* n) { right = n; } getLeft()493 TIntermTyped* getLeft() const { return left; } getRight()494 TIntermTyped* getRight() const { return right; } 495 bool promote(TInfoSink&); 496 497 protected: 498 TIntermTyped* left; 499 TIntermTyped* right; 500 }; 501 502 // 503 // Nodes for unary math operators. 504 // 505 class TIntermUnary : public TIntermOperator { 506 public: TIntermUnary(TOperator o,TType & t)507 TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0) {} TIntermUnary(TOperator o)508 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0) {} 509 setType(const TType & t)510 void setType(const TType &t) override 511 { 512 type = t; 513 514 if(operand->getQualifier() == EvqConstExpr) 515 { 516 type.setQualifier(EvqConstExpr); 517 } 518 } 519 520 virtual void traverse(TIntermTraverser*); getAsUnaryNode()521 virtual TIntermUnary* getAsUnaryNode() { return this; } 522 setOperand(TIntermTyped * o)523 void setOperand(TIntermTyped* o) { operand = o; } getOperand()524 TIntermTyped* getOperand() { return operand; } 525 bool promote(TInfoSink&, const TType *funcReturnType); 526 527 protected: 528 TIntermTyped* operand; 529 }; 530 531 typedef TVector<TIntermNode*> TIntermSequence; 532 typedef TVector<int> TQualifierList; 533 534 // 535 // Nodes that operate on an arbitrary sized set of children. 536 // 537 class TIntermAggregate : public TIntermOperator { 538 public: TIntermAggregate()539 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false) { endLine = { 0, 0, 0, 0 }; } TIntermAggregate(TOperator o)540 TIntermAggregate(TOperator o) : TIntermOperator(o) { } ~TIntermAggregate()541 ~TIntermAggregate() { } 542 getAsAggregate()543 virtual TIntermAggregate* getAsAggregate() { return this; } 544 virtual void traverse(TIntermTraverser*); 545 getSequence()546 TIntermSequence& getSequence() { return sequence; } 547 setType(const TType & t)548 void setType(const TType &t) override 549 { 550 type = t; 551 552 if(op != EOpFunctionCall) 553 { 554 for(TIntermNode *node : sequence) 555 { 556 if(!node->getAsTyped() || node->getAsTyped()->getQualifier() != EvqConstExpr) 557 { 558 return; 559 } 560 } 561 562 type.setQualifier(EvqConstExpr); 563 } 564 } 565 setName(const TString & n)566 void setName(const TString& n) { name = n; } getName()567 const TString& getName() const { return name; } 568 setUserDefined()569 void setUserDefined() { userDefined = true; } isUserDefined()570 bool isUserDefined() const { return userDefined; } 571 setOptimize(bool o)572 void setOptimize(bool o) { optimize = o; } getOptimize()573 bool getOptimize() { return optimize; } setDebug(bool d)574 void setDebug(bool d) { debug = d; } getDebug()575 bool getDebug() { return debug; } 576 setEndLine(const TSourceLoc & line)577 void setEndLine(const TSourceLoc& line) { endLine = line; } getEndLine()578 const TSourceLoc& getEndLine() const { return endLine; } 579 isConstantFoldable()580 bool isConstantFoldable() 581 { 582 for(TIntermNode *node : sequence) 583 { 584 if(!node->getAsConstantUnion() || !node->getAsConstantUnion()->getUnionArrayPointer()) 585 { 586 return false; 587 } 588 } 589 590 return true; 591 } 592 593 protected: 594 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor 595 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator 596 TIntermSequence sequence; 597 TString name; 598 bool userDefined; // used for user defined function names 599 600 bool optimize; 601 bool debug; 602 TSourceLoc endLine; 603 }; 604 605 // 606 // For if tests. Simplified since there is no switch statement. 607 // 608 class TIntermSelection : public TIntermTyped { 609 public: TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB)610 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : 611 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} TIntermSelection(TIntermTyped * cond,TIntermNode * trueB,TIntermNode * falseB,const TType & type)612 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : 613 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) 614 { 615 this->type.setQualifier(EvqTemporary); 616 } 617 618 virtual void traverse(TIntermTraverser*); 619 usesTernaryOperator()620 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } getCondition()621 TIntermTyped* getCondition() const { return condition; } getTrueBlock()622 TIntermNode* getTrueBlock() const { return trueBlock; } getFalseBlock()623 TIntermNode* getFalseBlock() const { return falseBlock; } getAsSelectionNode()624 TIntermSelection* getAsSelectionNode() { return this; } 625 626 protected: 627 TIntermTyped* condition; 628 TIntermNode* trueBlock; 629 TIntermNode* falseBlock; 630 }; 631 632 // 633 // Switch statement. 634 // 635 class TIntermSwitch : public TIntermNode 636 { 637 public: TIntermSwitch(TIntermTyped * init,TIntermAggregate * statementList)638 TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList) 639 : TIntermNode(), mInit(init), mStatementList(statementList) 640 {} 641 642 void traverse(TIntermTraverser *it); 643 getAsSwitchNode()644 TIntermSwitch *getAsSwitchNode() { return this; } 645 getInit()646 TIntermTyped *getInit() { return mInit; } getStatementList()647 TIntermAggregate *getStatementList() { return mStatementList; } setStatementList(TIntermAggregate * statementList)648 void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; } 649 650 protected: 651 TIntermTyped *mInit; 652 TIntermAggregate *mStatementList; 653 }; 654 655 // 656 // Case label. 657 // 658 class TIntermCase : public TIntermNode 659 { 660 public: TIntermCase(TIntermTyped * condition)661 TIntermCase(TIntermTyped *condition) 662 : TIntermNode(), mCondition(condition) 663 {} 664 665 void traverse(TIntermTraverser *it); 666 getAsCaseNode()667 TIntermCase *getAsCaseNode() { return this; } 668 hasCondition()669 bool hasCondition() const { return mCondition != nullptr; } getCondition()670 TIntermTyped *getCondition() const { return mCondition; } 671 672 protected: 673 TIntermTyped *mCondition; 674 }; 675 676 enum Visit 677 { 678 PreVisit, 679 InVisit, 680 PostVisit 681 }; 682 683 // 684 // For traversing the tree. User should derive from this, 685 // put their traversal specific data in it, and then pass 686 // it to a Traverse method. 687 // 688 // When using this, just fill in the methods for nodes you want visited. 689 // Return false from a pre-visit to skip visiting that node's subtree. 690 // 691 class TIntermTraverser 692 { 693 public: 694 POOL_ALLOCATOR_NEW_DELETE(); 695 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : preVisit(preVisit)696 preVisit(preVisit), 697 inVisit(inVisit), 698 postVisit(postVisit), 699 rightToLeft(rightToLeft), 700 mDepth(0) {} ~TIntermTraverser()701 virtual ~TIntermTraverser() {}; 702 visitSymbol(TIntermSymbol *)703 virtual void visitSymbol(TIntermSymbol*) {} visitConstantUnion(TIntermConstantUnion *)704 virtual void visitConstantUnion(TIntermConstantUnion*) {} visitBinary(Visit visit,TIntermBinary *)705 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} visitUnary(Visit visit,TIntermUnary *)706 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} visitSelection(Visit visit,TIntermSelection *)707 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} visitAggregate(Visit visit,TIntermAggregate *)708 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} visitLoop(Visit visit,TIntermLoop *)709 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} visitBranch(Visit visit,TIntermBranch *)710 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} visitSwitch(Visit,TIntermSwitch *)711 virtual bool visitSwitch(Visit, TIntermSwitch*) { return true; } visitCase(Visit,TIntermCase *)712 virtual bool visitCase(Visit, TIntermCase*) { return true; } 713 incrementDepth(TIntermNode * current)714 void incrementDepth(TIntermNode *current) 715 { 716 mDepth++; 717 mPath.push_back(current); 718 } 719 decrementDepth()720 void decrementDepth() 721 { 722 mDepth--; 723 mPath.pop_back(); 724 } 725 getParentNode()726 TIntermNode *getParentNode() 727 { 728 return mPath.size() == 0 ? nullptr : mPath.back(); 729 } 730 731 const bool preVisit; 732 const bool inVisit; 733 const bool postVisit; 734 const bool rightToLeft; 735 736 protected: 737 int mDepth; 738 739 // All the nodes from root to the current node's parent during traversing. 740 TVector<TIntermNode *> mPath; 741 742 private: 743 struct ParentBlock 744 { ParentBlockParentBlock745 ParentBlock(TIntermAggregate *nodeIn, TIntermSequence::size_type posIn) 746 : node(nodeIn), pos(posIn) 747 {} 748 749 TIntermAggregate *node; 750 TIntermSequence::size_type pos; 751 }; 752 // All the code blocks from the root to the current node's parent during traversal. 753 std::vector<ParentBlock> mParentBlockStack; 754 }; 755 756 #endif // __INTERMEDIATE_H 757