IntermRebuild.cpp (28430B)
1 // 2 // Copyright 2020 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 #include <algorithm> 8 9 #include "compiler/translator/Compiler.h" 10 #include "compiler/translator/SymbolTable.h" 11 #include "compiler/translator/tree_util/AsNode.h" 12 #include "compiler/translator/tree_util/IntermRebuild.h" 13 14 #define GUARD2(cond, failVal) \ 15 do \ 16 { \ 17 if (!(cond)) \ 18 { \ 19 return failVal; \ 20 } \ 21 } while (false) 22 23 #define GUARD(cond) GUARD2(cond, nullptr) 24 25 namespace sh 26 { 27 28 template <typename T, typename U> 29 ANGLE_INLINE bool AllBits(T haystack, U needle) 30 { 31 return (haystack & needle) == needle; 32 } 33 34 template <typename T, typename U> 35 ANGLE_INLINE bool AnyBits(T haystack, U needle) 36 { 37 return (haystack & needle) != 0; 38 } 39 40 //////////////////////////////////////////////////////////////////////////////// 41 42 TIntermRebuild::BaseResult::BaseResult(BaseResult &other) 43 : mAction(other.mAction), 44 mVisit(other.mVisit), 45 mSingle(other.mSingle), 46 mMulti(std::move(other.mMulti)) 47 {} 48 49 TIntermRebuild::BaseResult::BaseResult(TIntermNode &node, VisitBits visit) 50 : mAction(Action::ReplaceSingle), mVisit(visit), mSingle(&node) 51 {} 52 53 TIntermRebuild::BaseResult::BaseResult(TIntermNode *node, VisitBits visit) 54 : mAction(node ? Action::ReplaceSingle : Action::Drop), 55 mVisit(node ? visit : VisitBits::Neither), 56 mSingle(node) 57 {} 58 59 TIntermRebuild::BaseResult::BaseResult(std::nullptr_t) 60 : mAction(Action::Drop), mVisit(VisitBits::Neither), mSingle(nullptr) 61 {} 62 63 TIntermRebuild::BaseResult::BaseResult(Fail) 64 : mAction(Action::Fail), mVisit(VisitBits::Neither), mSingle(nullptr) 65 {} 66 67 TIntermRebuild::BaseResult::BaseResult(std::vector<TIntermNode *> &&nodes) 68 : mAction(Action::ReplaceMulti), 69 mVisit(VisitBits::Neither), 70 mSingle(nullptr), 71 mMulti(std::move(nodes)) 72 {} 73 74 void TIntermRebuild::BaseResult::moveAssignImpl(BaseResult &other) 75 { 76 mAction = other.mAction; 77 mVisit = other.mVisit; 78 mSingle = other.mSingle; 79 mMulti = std::move(other.mMulti); 80 } 81 82 TIntermRebuild::BaseResult TIntermRebuild::BaseResult::Multi(std::vector<TIntermNode *> &&nodes) 83 { 84 auto it = std::remove(nodes.begin(), nodes.end(), nullptr); 85 nodes.erase(it, nodes.end()); 86 return std::move(nodes); 87 } 88 89 bool TIntermRebuild::BaseResult::isFail() const 90 { 91 return mAction == Action::Fail; 92 } 93 94 bool TIntermRebuild::BaseResult::isDrop() const 95 { 96 return mAction == Action::Drop; 97 } 98 99 TIntermNode *TIntermRebuild::BaseResult::single() const 100 { 101 return mSingle; 102 } 103 104 const std::vector<TIntermNode *> *TIntermRebuild::BaseResult::multi() const 105 { 106 if (mAction == Action::ReplaceMulti) 107 { 108 return &mMulti; 109 } 110 return nullptr; 111 } 112 113 //////////////////////////////////////////////////////////////////////////////// 114 115 using PreResult = TIntermRebuild::PreResult; 116 117 PreResult::PreResult(TIntermNode &node, VisitBits visit) : BaseResult(node, visit) {} 118 PreResult::PreResult(TIntermNode *node, VisitBits visit) : BaseResult(node, visit) {} 119 PreResult::PreResult(std::nullptr_t) : BaseResult(nullptr) {} 120 PreResult::PreResult(Fail) : BaseResult(Fail()) {} 121 122 PreResult::PreResult(BaseResult &&other) : BaseResult(other) {} 123 PreResult::PreResult(PreResult &&other) : BaseResult(other) {} 124 125 void PreResult::operator=(PreResult &&other) 126 { 127 moveAssignImpl(other); 128 } 129 130 //////////////////////////////////////////////////////////////////////////////// 131 132 using PostResult = TIntermRebuild::PostResult; 133 134 PostResult::PostResult(TIntermNode &node) : BaseResult(node, VisitBits::Neither) {} 135 PostResult::PostResult(TIntermNode *node) : BaseResult(node, VisitBits::Neither) {} 136 PostResult::PostResult(std::nullptr_t) : BaseResult(nullptr) {} 137 PostResult::PostResult(Fail) : BaseResult(Fail()) {} 138 139 PostResult::PostResult(PostResult &&other) : BaseResult(other) {} 140 PostResult::PostResult(BaseResult &&other) : BaseResult(other) {} 141 142 void PostResult::operator=(PostResult &&other) 143 { 144 moveAssignImpl(other); 145 } 146 147 //////////////////////////////////////////////////////////////////////////////// 148 149 TIntermRebuild::TIntermRebuild(TCompiler &compiler, bool preVisit, bool postVisit) 150 : mCompiler(compiler), 151 mSymbolTable(compiler.getSymbolTable()), 152 mPreVisit(preVisit), 153 mPostVisit(postVisit) 154 { 155 ASSERT(preVisit || postVisit); 156 } 157 158 TIntermRebuild::~TIntermRebuild() 159 { 160 ASSERT(!mNodeStack.value); 161 ASSERT(!mNodeStack.tail); 162 } 163 164 const TFunction *TIntermRebuild::getParentFunction() const 165 { 166 return mParentFunc; 167 } 168 169 TIntermNode *TIntermRebuild::getParentNode(size_t offset) const 170 { 171 ASSERT(mNodeStack.tail); 172 auto parent = *mNodeStack.tail; 173 while (offset > 0) 174 { 175 --offset; 176 ASSERT(parent.tail); 177 parent = *parent.tail; 178 } 179 return parent.value; 180 } 181 182 bool TIntermRebuild::rebuildRoot(TIntermBlock &root) 183 { 184 if (!rebuildInPlace(root)) 185 { 186 return false; 187 } 188 return mCompiler.validateAST(&root); 189 } 190 191 bool TIntermRebuild::rebuildInPlace(TIntermAggregate &node) 192 { 193 return rebuildInPlaceImpl(node); 194 } 195 196 bool TIntermRebuild::rebuildInPlace(TIntermBlock &node) 197 { 198 return rebuildInPlaceImpl(node); 199 } 200 201 bool TIntermRebuild::rebuildInPlace(TIntermDeclaration &node) 202 { 203 return rebuildInPlaceImpl(node); 204 } 205 206 template <typename Node> 207 bool TIntermRebuild::rebuildInPlaceImpl(Node &node) 208 { 209 auto *newNode = traverseAnyAs<Node>(node); 210 if (!newNode) 211 { 212 return false; 213 } 214 215 if (newNode != &node) 216 { 217 *node.getSequence() = std::move(*newNode->getSequence()); 218 } 219 220 return true; 221 } 222 223 PostResult TIntermRebuild::rebuild(TIntermNode &node) 224 { 225 return traverseAny(node); 226 } 227 228 //////////////////////////////////////////////////////////////////////////////// 229 230 template <typename Node> 231 Node *TIntermRebuild::traverseAnyAs(TIntermNode &node) 232 { 233 PostResult result(traverseAny(node)); 234 if (result.mAction == Action::Fail || !result.mSingle) 235 { 236 return nullptr; 237 } 238 return asNode<Node>(result.mSingle); 239 } 240 241 template <typename Node> 242 bool TIntermRebuild::traverseAnyAs(TIntermNode &node, Node *&out) 243 { 244 PostResult result(traverseAny(node)); 245 if (result.mAction == Action::Fail || result.mAction == Action::ReplaceMulti) 246 { 247 return false; 248 } 249 if (!result.mSingle) 250 { 251 return true; 252 } 253 out = asNode<Node>(result.mSingle); 254 return out != nullptr; 255 } 256 257 bool TIntermRebuild::traverseAggregateBaseChildren(TIntermAggregateBase &node) 258 { 259 auto *const children = node.getSequence(); 260 ASSERT(children); 261 TIntermSequence newChildren; 262 263 for (TIntermNode *child : *children) 264 { 265 ASSERT(child); 266 PostResult result(traverseAny(*child)); 267 268 switch (result.mAction) 269 { 270 case Action::ReplaceSingle: 271 newChildren.push_back(result.mSingle); 272 break; 273 274 case Action::ReplaceMulti: 275 for (TIntermNode *newNode : result.mMulti) 276 { 277 if (newNode) 278 { 279 newChildren.push_back(newNode); 280 } 281 } 282 break; 283 284 case Action::Drop: 285 break; 286 287 case Action::Fail: 288 return false; 289 290 default: 291 ASSERT(false); 292 return false; 293 } 294 } 295 296 *children = std::move(newChildren); 297 298 return true; 299 } 300 301 //////////////////////////////////////////////////////////////////////////////// 302 303 struct TIntermRebuild::NodeStackGuard 304 { 305 ConsList<TIntermNode *> oldNodeStack; 306 ConsList<TIntermNode *> &nodeStack; 307 NodeStackGuard(ConsList<TIntermNode *> &nodeStack, TIntermNode *node) 308 : oldNodeStack(nodeStack), nodeStack(nodeStack) 309 { 310 nodeStack = {node, &oldNodeStack}; 311 } 312 ~NodeStackGuard() { nodeStack = oldNodeStack; } 313 }; 314 315 PostResult TIntermRebuild::traverseAny(TIntermNode &originalNode) 316 { 317 PreResult preResult = traversePre(originalNode); 318 if (!preResult.mSingle) 319 { 320 ASSERT(preResult.mVisit == VisitBits::Neither); 321 return std::move(preResult); 322 } 323 324 TIntermNode *currNode = preResult.mSingle; 325 const VisitBits visit = preResult.mVisit; 326 const NodeType currNodeType = getNodeType(*currNode); 327 328 currNode = traverseChildren(currNodeType, originalNode, *currNode, visit); 329 if (!currNode) 330 { 331 return Fail(); 332 } 333 334 return traversePost(currNodeType, originalNode, *currNode, visit); 335 } 336 337 PreResult TIntermRebuild::traversePre(TIntermNode &originalNode) 338 { 339 if (!mPreVisit) 340 { 341 return {originalNode, VisitBits::Both}; 342 } 343 344 NodeStackGuard guard(mNodeStack, &originalNode); 345 346 const NodeType originalNodeType = getNodeType(originalNode); 347 348 switch (originalNodeType) 349 { 350 case NodeType::Unknown: 351 ASSERT(false); 352 return Fail(); 353 case NodeType::Symbol: 354 return visitSymbolPre(*originalNode.getAsSymbolNode()); 355 case NodeType::ConstantUnion: 356 return visitConstantUnionPre(*originalNode.getAsConstantUnion()); 357 case NodeType::FunctionPrototype: 358 return visitFunctionPrototypePre(*originalNode.getAsFunctionPrototypeNode()); 359 case NodeType::PreprocessorDirective: 360 return visitPreprocessorDirectivePre(*originalNode.getAsPreprocessorDirective()); 361 case NodeType::Unary: 362 return visitUnaryPre(*originalNode.getAsUnaryNode()); 363 case NodeType::Binary: 364 return visitBinaryPre(*originalNode.getAsBinaryNode()); 365 case NodeType::Ternary: 366 return visitTernaryPre(*originalNode.getAsTernaryNode()); 367 case NodeType::Swizzle: 368 return visitSwizzlePre(*originalNode.getAsSwizzleNode()); 369 case NodeType::IfElse: 370 return visitIfElsePre(*originalNode.getAsIfElseNode()); 371 case NodeType::Switch: 372 return visitSwitchPre(*originalNode.getAsSwitchNode()); 373 case NodeType::Case: 374 return visitCasePre(*originalNode.getAsCaseNode()); 375 case NodeType::FunctionDefinition: 376 return visitFunctionDefinitionPre(*originalNode.getAsFunctionDefinition()); 377 case NodeType::Aggregate: 378 return visitAggregatePre(*originalNode.getAsAggregate()); 379 case NodeType::Block: 380 return visitBlockPre(*originalNode.getAsBlock()); 381 case NodeType::GlobalQualifierDeclaration: 382 return visitGlobalQualifierDeclarationPre( 383 *originalNode.getAsGlobalQualifierDeclarationNode()); 384 case NodeType::Declaration: 385 return visitDeclarationPre(*originalNode.getAsDeclarationNode()); 386 case NodeType::Loop: 387 return visitLoopPre(*originalNode.getAsLoopNode()); 388 case NodeType::Branch: 389 return visitBranchPre(*originalNode.getAsBranchNode()); 390 default: 391 ASSERT(false); 392 return Fail(); 393 } 394 } 395 396 TIntermNode *TIntermRebuild::traverseChildren(NodeType currNodeType, 397 const TIntermNode &originalNode, 398 TIntermNode &currNode, 399 VisitBits visit) 400 { 401 if (!AnyBits(visit, VisitBits::Children)) 402 { 403 return &currNode; 404 } 405 406 if (AnyBits(visit, VisitBits::ChildrenRequiresSame) && &originalNode != &currNode) 407 { 408 return &currNode; 409 } 410 411 NodeStackGuard guard(mNodeStack, &currNode); 412 413 switch (currNodeType) 414 { 415 case NodeType::Unknown: 416 ASSERT(false); 417 return nullptr; 418 case NodeType::Symbol: 419 return &currNode; 420 case NodeType::ConstantUnion: 421 return &currNode; 422 case NodeType::FunctionPrototype: 423 return &currNode; 424 case NodeType::PreprocessorDirective: 425 return &currNode; 426 case NodeType::Unary: 427 return traverseUnaryChildren(*currNode.getAsUnaryNode()); 428 case NodeType::Binary: 429 return traverseBinaryChildren(*currNode.getAsBinaryNode()); 430 case NodeType::Ternary: 431 return traverseTernaryChildren(*currNode.getAsTernaryNode()); 432 case NodeType::Swizzle: 433 return traverseSwizzleChildren(*currNode.getAsSwizzleNode()); 434 case NodeType::IfElse: 435 return traverseIfElseChildren(*currNode.getAsIfElseNode()); 436 case NodeType::Switch: 437 return traverseSwitchChildren(*currNode.getAsSwitchNode()); 438 case NodeType::Case: 439 return traverseCaseChildren(*currNode.getAsCaseNode()); 440 case NodeType::FunctionDefinition: 441 return traverseFunctionDefinitionChildren(*currNode.getAsFunctionDefinition()); 442 case NodeType::Aggregate: 443 return traverseAggregateChildren(*currNode.getAsAggregate()); 444 case NodeType::Block: 445 return traverseBlockChildren(*currNode.getAsBlock()); 446 case NodeType::GlobalQualifierDeclaration: 447 return traverseGlobalQualifierDeclarationChildren( 448 *currNode.getAsGlobalQualifierDeclarationNode()); 449 case NodeType::Declaration: 450 return traverseDeclarationChildren(*currNode.getAsDeclarationNode()); 451 case NodeType::Loop: 452 return traverseLoopChildren(*currNode.getAsLoopNode()); 453 case NodeType::Branch: 454 return traverseBranchChildren(*currNode.getAsBranchNode()); 455 default: 456 ASSERT(false); 457 return nullptr; 458 } 459 } 460 461 PostResult TIntermRebuild::traversePost(NodeType currNodeType, 462 const TIntermNode &originalNode, 463 TIntermNode &currNode, 464 VisitBits visit) 465 { 466 if (!mPostVisit) 467 { 468 return currNode; 469 } 470 471 if (!AnyBits(visit, VisitBits::Post)) 472 { 473 return currNode; 474 } 475 476 if (AnyBits(visit, VisitBits::PostRequiresSame) && &originalNode != &currNode) 477 { 478 return currNode; 479 } 480 481 NodeStackGuard guard(mNodeStack, &currNode); 482 483 switch (currNodeType) 484 { 485 case NodeType::Unknown: 486 ASSERT(false); 487 return Fail(); 488 case NodeType::Symbol: 489 return visitSymbolPost(*currNode.getAsSymbolNode()); 490 case NodeType::ConstantUnion: 491 return visitConstantUnionPost(*currNode.getAsConstantUnion()); 492 case NodeType::FunctionPrototype: 493 return visitFunctionPrototypePost(*currNode.getAsFunctionPrototypeNode()); 494 case NodeType::PreprocessorDirective: 495 return visitPreprocessorDirectivePost(*currNode.getAsPreprocessorDirective()); 496 case NodeType::Unary: 497 return visitUnaryPost(*currNode.getAsUnaryNode()); 498 case NodeType::Binary: 499 return visitBinaryPost(*currNode.getAsBinaryNode()); 500 case NodeType::Ternary: 501 return visitTernaryPost(*currNode.getAsTernaryNode()); 502 case NodeType::Swizzle: 503 return visitSwizzlePost(*currNode.getAsSwizzleNode()); 504 case NodeType::IfElse: 505 return visitIfElsePost(*currNode.getAsIfElseNode()); 506 case NodeType::Switch: 507 return visitSwitchPost(*currNode.getAsSwitchNode()); 508 case NodeType::Case: 509 return visitCasePost(*currNode.getAsCaseNode()); 510 case NodeType::FunctionDefinition: 511 return visitFunctionDefinitionPost(*currNode.getAsFunctionDefinition()); 512 case NodeType::Aggregate: 513 return visitAggregatePost(*currNode.getAsAggregate()); 514 case NodeType::Block: 515 return visitBlockPost(*currNode.getAsBlock()); 516 case NodeType::GlobalQualifierDeclaration: 517 return visitGlobalQualifierDeclarationPost( 518 *currNode.getAsGlobalQualifierDeclarationNode()); 519 case NodeType::Declaration: 520 return visitDeclarationPost(*currNode.getAsDeclarationNode()); 521 case NodeType::Loop: 522 return visitLoopPost(*currNode.getAsLoopNode()); 523 case NodeType::Branch: 524 return visitBranchPost(*currNode.getAsBranchNode()); 525 default: 526 ASSERT(false); 527 return Fail(); 528 } 529 } 530 531 //////////////////////////////////////////////////////////////////////////////// 532 533 TIntermNode *TIntermRebuild::traverseAggregateChildren(TIntermAggregate &node) 534 { 535 if (traverseAggregateBaseChildren(node)) 536 { 537 return &node; 538 } 539 return nullptr; 540 } 541 542 TIntermNode *TIntermRebuild::traverseBlockChildren(TIntermBlock &node) 543 { 544 if (traverseAggregateBaseChildren(node)) 545 { 546 return &node; 547 } 548 return nullptr; 549 } 550 551 TIntermNode *TIntermRebuild::traverseDeclarationChildren(TIntermDeclaration &node) 552 { 553 if (traverseAggregateBaseChildren(node)) 554 { 555 return &node; 556 } 557 return nullptr; 558 } 559 560 TIntermNode *TIntermRebuild::traverseSwizzleChildren(TIntermSwizzle &node) 561 { 562 auto *const operand = node.getOperand(); 563 ASSERT(operand); 564 565 auto *newOperand = traverseAnyAs<TIntermTyped>(*operand); 566 GUARD(newOperand); 567 568 if (newOperand != operand) 569 { 570 return new TIntermSwizzle(newOperand, node.getSwizzleOffsets()); 571 } 572 573 return &node; 574 } 575 576 TIntermNode *TIntermRebuild::traverseBinaryChildren(TIntermBinary &node) 577 { 578 auto *const left = node.getLeft(); 579 ASSERT(left); 580 auto *const right = node.getRight(); 581 ASSERT(right); 582 583 auto *const newLeft = traverseAnyAs<TIntermTyped>(*left); 584 GUARD(newLeft); 585 auto *const newRight = traverseAnyAs<TIntermTyped>(*right); 586 GUARD(newRight); 587 588 if (newLeft != left || newRight != right) 589 { 590 TOperator op = node.getOp(); 591 switch (op) 592 { 593 case TOperator::EOpIndexDirectStruct: 594 { 595 if (newLeft->getType().getInterfaceBlock()) 596 { 597 op = TOperator::EOpIndexDirectInterfaceBlock; 598 } 599 } 600 break; 601 602 case TOperator::EOpIndexDirectInterfaceBlock: 603 { 604 if (newLeft->getType().getStruct()) 605 { 606 op = TOperator::EOpIndexDirectStruct; 607 } 608 } 609 break; 610 611 case TOperator::EOpComma: 612 return TIntermBinary::CreateComma(newLeft, newRight, mCompiler.getShaderVersion()); 613 614 default: 615 break; 616 } 617 618 return new TIntermBinary(op, newLeft, newRight); 619 } 620 621 return &node; 622 } 623 624 TIntermNode *TIntermRebuild::traverseUnaryChildren(TIntermUnary &node) 625 { 626 auto *const operand = node.getOperand(); 627 ASSERT(operand); 628 629 auto *const newOperand = traverseAnyAs<TIntermTyped>(*operand); 630 GUARD(newOperand); 631 632 if (newOperand != operand) 633 { 634 return new TIntermUnary(node.getOp(), newOperand, node.getFunction()); 635 } 636 637 return &node; 638 } 639 640 TIntermNode *TIntermRebuild::traverseTernaryChildren(TIntermTernary &node) 641 { 642 auto *const cond = node.getCondition(); 643 ASSERT(cond); 644 auto *const true_ = node.getTrueExpression(); 645 ASSERT(true_); 646 auto *const false_ = node.getFalseExpression(); 647 ASSERT(false_); 648 649 auto *const newCond = traverseAnyAs<TIntermTyped>(*cond); 650 GUARD(newCond); 651 auto *const newTrue = traverseAnyAs<TIntermTyped>(*true_); 652 GUARD(newTrue); 653 auto *const newFalse = traverseAnyAs<TIntermTyped>(*false_); 654 GUARD(newFalse); 655 656 if (newCond != cond || newTrue != true_ || newFalse != false_) 657 { 658 return new TIntermTernary(newCond, newTrue, newFalse); 659 } 660 661 return &node; 662 } 663 664 TIntermNode *TIntermRebuild::traverseIfElseChildren(TIntermIfElse &node) 665 { 666 auto *const cond = node.getCondition(); 667 ASSERT(cond); 668 auto *const true_ = node.getTrueBlock(); 669 auto *const false_ = node.getFalseBlock(); 670 671 auto *const newCond = traverseAnyAs<TIntermTyped>(*cond); 672 GUARD(newCond); 673 TIntermBlock *newTrue = nullptr; 674 if (true_) 675 { 676 GUARD(traverseAnyAs(*true_, newTrue)); 677 } 678 TIntermBlock *newFalse = nullptr; 679 if (false_) 680 { 681 GUARD(traverseAnyAs(*false_, newFalse)); 682 } 683 684 if (newCond != cond || newTrue != true_ || newFalse != false_) 685 { 686 return new TIntermIfElse(newCond, newTrue, newFalse); 687 } 688 689 return &node; 690 } 691 692 TIntermNode *TIntermRebuild::traverseSwitchChildren(TIntermSwitch &node) 693 { 694 auto *const init = node.getInit(); 695 ASSERT(init); 696 auto *const stmts = node.getStatementList(); 697 ASSERT(stmts); 698 699 auto *const newInit = traverseAnyAs<TIntermTyped>(*init); 700 GUARD(newInit); 701 auto *const newStmts = traverseAnyAs<TIntermBlock>(*stmts); 702 GUARD(newStmts); 703 704 if (newInit != init || newStmts != stmts) 705 { 706 return new TIntermSwitch(newInit, newStmts); 707 } 708 709 return &node; 710 } 711 712 TIntermNode *TIntermRebuild::traverseCaseChildren(TIntermCase &node) 713 { 714 auto *const cond = node.getCondition(); 715 716 TIntermTyped *newCond = nullptr; 717 if (cond) 718 { 719 GUARD(traverseAnyAs(*cond, newCond)); 720 } 721 722 if (newCond != cond) 723 { 724 return new TIntermCase(newCond); 725 } 726 727 return &node; 728 } 729 730 TIntermNode *TIntermRebuild::traverseFunctionDefinitionChildren(TIntermFunctionDefinition &node) 731 { 732 GUARD(!mParentFunc); // Function definitions cannot be nested. 733 mParentFunc = node.getFunction(); 734 struct OnExit 735 { 736 const TFunction *&parentFunc; 737 OnExit(const TFunction *&parentFunc) : parentFunc(parentFunc) {} 738 ~OnExit() { parentFunc = nullptr; } 739 } onExit(mParentFunc); 740 741 auto *const proto = node.getFunctionPrototype(); 742 ASSERT(proto); 743 auto *const body = node.getBody(); 744 ASSERT(body); 745 746 auto *const newProto = traverseAnyAs<TIntermFunctionPrototype>(*proto); 747 GUARD(newProto); 748 auto *const newBody = traverseAnyAs<TIntermBlock>(*body); 749 GUARD(newBody); 750 751 if (newProto != proto || newBody != body) 752 { 753 return new TIntermFunctionDefinition(newProto, newBody); 754 } 755 756 return &node; 757 } 758 759 TIntermNode *TIntermRebuild::traverseGlobalQualifierDeclarationChildren( 760 TIntermGlobalQualifierDeclaration &node) 761 { 762 auto *const symbol = node.getSymbol(); 763 ASSERT(symbol); 764 765 auto *const newSymbol = traverseAnyAs<TIntermSymbol>(*symbol); 766 GUARD(newSymbol); 767 768 if (newSymbol != symbol) 769 { 770 return new TIntermGlobalQualifierDeclaration(newSymbol, node.isPrecise(), node.getLine()); 771 } 772 773 return &node; 774 } 775 776 TIntermNode *TIntermRebuild::traverseLoopChildren(TIntermLoop &node) 777 { 778 const TLoopType loopType = node.getType(); 779 780 auto *const init = node.getInit(); 781 auto *const cond = node.getCondition(); 782 auto *const expr = node.getExpression(); 783 auto *const body = node.getBody(); 784 ASSERT(body); 785 786 #if defined(ANGLE_ENABLE_ASSERTS) 787 switch (loopType) 788 { 789 case TLoopType::ELoopFor: 790 break; 791 case TLoopType::ELoopWhile: 792 case TLoopType::ELoopDoWhile: 793 ASSERT(cond); 794 ASSERT(!init && !expr); 795 break; 796 default: 797 ASSERT(false); 798 break; 799 } 800 #endif 801 802 auto *const newBody = traverseAnyAs<TIntermBlock>(*body); 803 GUARD(newBody); 804 TIntermNode *newInit = nullptr; 805 if (init) 806 { 807 GUARD(traverseAnyAs(*init, newInit)); 808 } 809 TIntermTyped *newCond = nullptr; 810 if (cond) 811 { 812 GUARD(traverseAnyAs(*cond, newCond)); 813 } 814 TIntermTyped *newExpr = nullptr; 815 if (expr) 816 { 817 GUARD(traverseAnyAs(*expr, newExpr)); 818 } 819 820 if (newInit != init || newCond != cond || newExpr != expr || newBody != body) 821 { 822 switch (loopType) 823 { 824 case TLoopType::ELoopFor: 825 GUARD(newBody); 826 break; 827 case TLoopType::ELoopWhile: 828 case TLoopType::ELoopDoWhile: 829 GUARD(newCond && newBody); 830 GUARD(!newInit && !newExpr); 831 break; 832 default: 833 ASSERT(false); 834 break; 835 } 836 return new TIntermLoop(loopType, newInit, newCond, newExpr, newBody); 837 } 838 839 return &node; 840 } 841 842 TIntermNode *TIntermRebuild::traverseBranchChildren(TIntermBranch &node) 843 { 844 auto *const expr = node.getExpression(); 845 846 TIntermTyped *newExpr = nullptr; 847 if (expr) 848 { 849 GUARD(traverseAnyAs<TIntermTyped>(*expr, newExpr)); 850 } 851 852 if (newExpr != expr) 853 { 854 return new TIntermBranch(node.getFlowOp(), newExpr); 855 } 856 857 return &node; 858 } 859 860 //////////////////////////////////////////////////////////////////////////////// 861 862 PreResult TIntermRebuild::visitSymbolPre(TIntermSymbol &node) 863 { 864 return {node, VisitBits::Both}; 865 } 866 867 PreResult TIntermRebuild::visitConstantUnionPre(TIntermConstantUnion &node) 868 { 869 return {node, VisitBits::Both}; 870 } 871 872 PreResult TIntermRebuild::visitFunctionPrototypePre(TIntermFunctionPrototype &node) 873 { 874 return {node, VisitBits::Both}; 875 } 876 877 PreResult TIntermRebuild::visitPreprocessorDirectivePre(TIntermPreprocessorDirective &node) 878 { 879 return {node, VisitBits::Both}; 880 } 881 882 PreResult TIntermRebuild::visitUnaryPre(TIntermUnary &node) 883 { 884 return {node, VisitBits::Both}; 885 } 886 887 PreResult TIntermRebuild::visitBinaryPre(TIntermBinary &node) 888 { 889 return {node, VisitBits::Both}; 890 } 891 892 PreResult TIntermRebuild::visitTernaryPre(TIntermTernary &node) 893 { 894 return {node, VisitBits::Both}; 895 } 896 897 PreResult TIntermRebuild::visitSwizzlePre(TIntermSwizzle &node) 898 { 899 return {node, VisitBits::Both}; 900 } 901 902 PreResult TIntermRebuild::visitIfElsePre(TIntermIfElse &node) 903 { 904 return {node, VisitBits::Both}; 905 } 906 907 PreResult TIntermRebuild::visitSwitchPre(TIntermSwitch &node) 908 { 909 return {node, VisitBits::Both}; 910 } 911 912 PreResult TIntermRebuild::visitCasePre(TIntermCase &node) 913 { 914 return {node, VisitBits::Both}; 915 } 916 917 PreResult TIntermRebuild::visitLoopPre(TIntermLoop &node) 918 { 919 return {node, VisitBits::Both}; 920 } 921 922 PreResult TIntermRebuild::visitBranchPre(TIntermBranch &node) 923 { 924 return {node, VisitBits::Both}; 925 } 926 927 PreResult TIntermRebuild::visitDeclarationPre(TIntermDeclaration &node) 928 { 929 return {node, VisitBits::Both}; 930 } 931 932 PreResult TIntermRebuild::visitBlockPre(TIntermBlock &node) 933 { 934 return {node, VisitBits::Both}; 935 } 936 937 PreResult TIntermRebuild::visitAggregatePre(TIntermAggregate &node) 938 { 939 return {node, VisitBits::Both}; 940 } 941 942 PreResult TIntermRebuild::visitFunctionDefinitionPre(TIntermFunctionDefinition &node) 943 { 944 return {node, VisitBits::Both}; 945 } 946 947 PreResult TIntermRebuild::visitGlobalQualifierDeclarationPre( 948 TIntermGlobalQualifierDeclaration &node) 949 { 950 return {node, VisitBits::Both}; 951 } 952 953 //////////////////////////////////////////////////////////////////////////////// 954 955 PostResult TIntermRebuild::visitSymbolPost(TIntermSymbol &node) 956 { 957 return node; 958 } 959 960 PostResult TIntermRebuild::visitConstantUnionPost(TIntermConstantUnion &node) 961 { 962 return node; 963 } 964 965 PostResult TIntermRebuild::visitFunctionPrototypePost(TIntermFunctionPrototype &node) 966 { 967 return node; 968 } 969 970 PostResult TIntermRebuild::visitPreprocessorDirectivePost(TIntermPreprocessorDirective &node) 971 { 972 return node; 973 } 974 975 PostResult TIntermRebuild::visitUnaryPost(TIntermUnary &node) 976 { 977 return node; 978 } 979 980 PostResult TIntermRebuild::visitBinaryPost(TIntermBinary &node) 981 { 982 return node; 983 } 984 985 PostResult TIntermRebuild::visitTernaryPost(TIntermTernary &node) 986 { 987 return node; 988 } 989 990 PostResult TIntermRebuild::visitSwizzlePost(TIntermSwizzle &node) 991 { 992 return node; 993 } 994 995 PostResult TIntermRebuild::visitIfElsePost(TIntermIfElse &node) 996 { 997 return node; 998 } 999 1000 PostResult TIntermRebuild::visitSwitchPost(TIntermSwitch &node) 1001 { 1002 return node; 1003 } 1004 1005 PostResult TIntermRebuild::visitCasePost(TIntermCase &node) 1006 { 1007 return node; 1008 } 1009 1010 PostResult TIntermRebuild::visitLoopPost(TIntermLoop &node) 1011 { 1012 return node; 1013 } 1014 1015 PostResult TIntermRebuild::visitBranchPost(TIntermBranch &node) 1016 { 1017 return node; 1018 } 1019 1020 PostResult TIntermRebuild::visitDeclarationPost(TIntermDeclaration &node) 1021 { 1022 return node; 1023 } 1024 1025 PostResult TIntermRebuild::visitBlockPost(TIntermBlock &node) 1026 { 1027 return node; 1028 } 1029 1030 PostResult TIntermRebuild::visitAggregatePost(TIntermAggregate &node) 1031 { 1032 return node; 1033 } 1034 1035 PostResult TIntermRebuild::visitFunctionDefinitionPost(TIntermFunctionDefinition &node) 1036 { 1037 return node; 1038 } 1039 1040 PostResult TIntermRebuild::visitGlobalQualifierDeclarationPost( 1041 TIntermGlobalQualifierDeclaration &node) 1042 { 1043 return node; 1044 } 1045 1046 } // namespace sh