| 528 | } |
| 529 | |
| 530 | void StackLayoutGenerator::stitchConditionalJumps(CFG::BasicBlock const& _block) |
| 531 | { |
| 532 | util::BreadthFirstSearch<CFG::BasicBlock const*> breadthFirstSearch{{&_block}}; |
| 533 | breadthFirstSearch.run([&](CFG::BasicBlock const* _block, auto _addChild) { |
| 534 | auto& info = m_layout.blockInfos.at(_block); |
| 535 | std::visit(util::GenericVisitor{ |
| 536 | [&](CFG::BasicBlock::MainExit const&) {}, |
| 537 | [&](CFG::BasicBlock::Jump const& _jump) |
| 538 | { |
| 539 | if (!_jump.backwards) |
| 540 | _addChild(_jump.target); |
| 541 | }, |
| 542 | [&](CFG::BasicBlock::ConditionalJump const& _conditionalJump) |
| 543 | { |
| 544 | auto& zeroTargetInfo = m_layout.blockInfos.at(_conditionalJump.zero); |
| 545 | auto& nonZeroTargetInfo = m_layout.blockInfos.at(_conditionalJump.nonZero); |
| 546 | Stack exitLayout = info.exitLayout; |
| 547 | |
| 548 | // The last block must have produced the condition at the stack top. |
| 549 | yulAssert(!exitLayout.empty(), ""); |
| 550 | yulAssert(exitLayout.back() == _conditionalJump.condition, ""); |
| 551 | // The condition is consumed by the jump. |
| 552 | exitLayout.pop_back(); |
| 553 | |
| 554 | auto fixJumpTargetEntry = [&](Stack const& _originalEntryLayout) -> Stack { |
| 555 | Stack newEntryLayout = exitLayout; |
| 556 | // Whatever the block being jumped to does not actually require, can be marked as junk. |
| 557 | for (auto& slot: newEntryLayout) |
| 558 | if (!util::contains(_originalEntryLayout, slot)) |
| 559 | slot = JunkSlot{}; |
| 560 | // Make sure everything the block being jumped to requires is actually present or can be generated. |
| 561 | for (auto const& slot: _originalEntryLayout) |
| 562 | yulAssert(canBeFreelyGenerated(slot) || util::contains(newEntryLayout, slot), ""); |
| 563 | return newEntryLayout; |
| 564 | }; |
| 565 | zeroTargetInfo.entryLayout = fixJumpTargetEntry(zeroTargetInfo.entryLayout); |
| 566 | nonZeroTargetInfo.entryLayout = fixJumpTargetEntry(nonZeroTargetInfo.entryLayout); |
| 567 | _addChild(_conditionalJump.zero); |
| 568 | _addChild(_conditionalJump.nonZero); |
| 569 | }, |
| 570 | [&](CFG::BasicBlock::FunctionReturn const&) {}, |
| 571 | [&](CFG::BasicBlock::Terminated const&) { }, |
| 572 | }, _block->exit); |
| 573 | }); |
| 574 | } |
| 575 | |
| 576 | Stack StackLayoutGenerator::combineStack(Stack const& _stack1, Stack const& _stack2, size_t _reachableStackDepth) |
| 577 | { |
nothing calls this directly
no test coverage detected