MCPcopy Create free account
hub / github.com/argotorg/solidity / fillInJunk

Method fillInJunk

libyul/backends/evm/StackLayoutGenerator.cpp:739–875  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

737}
738
739void StackLayoutGenerator::fillInJunk(CFG::BasicBlock const& _block, CFG::FunctionInfo const* _functionInfo)
740{
741 /// Recursively adds junk to the subgraph starting on @a _entry.
742 /// Since it is only called on cut-vertices, the full subgraph retains proper stack balance.
743 auto addJunkRecursive = [&](CFG::BasicBlock const* _entry, size_t _numJunk) {
744 util::BreadthFirstSearch<CFG::BasicBlock const*> breadthFirstSearch{{_entry}};
745 breadthFirstSearch.run([&](CFG::BasicBlock const* _block, auto _addChild) {
746 auto& blockInfo = m_layout.blockInfos.at(_block);
747 blockInfo.entryLayout = Stack{_numJunk, JunkSlot{}} + std::move(blockInfo.entryLayout);
748 for (auto const& operation: _block->operations)
749 {
750 auto& operationEntryLayout = m_layout.operationEntryLayout.at(&operation);
751 operationEntryLayout = Stack{_numJunk, JunkSlot{}} + std::move(operationEntryLayout);
752 }
753 blockInfo.exitLayout = Stack{_numJunk, JunkSlot{}} + std::move(blockInfo.exitLayout);
754
755 std::visit(util::GenericVisitor{
756 [&](CFG::BasicBlock::MainExit const&) {},
757 [&](CFG::BasicBlock::Jump const& _jump)
758 {
759 _addChild(_jump.target);
760 },
761 [&](CFG::BasicBlock::ConditionalJump const& _conditionalJump)
762 {
763 _addChild(_conditionalJump.zero);
764 _addChild(_conditionalJump.nonZero);
765 },
766 [&](CFG::BasicBlock::FunctionReturn const&) { yulAssert(!simulateFunctionsWithJumps()); },
767 [&](CFG::BasicBlock::Terminated const&) {},
768 }, _block->exit);
769 });
770 };
771 /// @returns the number of operations required to transform @a _source to @a _target.
772 auto evaluateTransform = [&](Stack _source, Stack const& _target) -> size_t {
773 size_t opGas = 0;
774 auto swap = [&](unsigned _swapDepth)
775 {
776 if (_swapDepth > reachableStackDepth())
777 opGas += 1000;
778 else
779 opGas += evmasm::GasMeter::swapGas(_swapDepth, m_evmDialect.evmVersion());
780 };
781 auto dupOrPush = [&](StackSlot const& _slot)
782 {
783 if (canBeFreelyGenerated(_slot))
784 opGas += evmasm::GasMeter::runGas(evmasm::pushInstruction(32), m_evmDialect.evmVersion());
785 else
786 {
787 if (auto depth = util::findOffset(_source | ranges::views::reverse, _slot))
788 {
789 if (*depth < reachableStackDepth())
790 opGas += evmasm::GasMeter::dupGas(*depth + 1, m_evmDialect.evmVersion());
791 else
792 opGas += 1000;
793 }
794 else
795 {
796 // This has to be a previously unassigned return variable.

Callers

nothing calls this directly

Calls 11

canBeFreelyGeneratedFunction · 0.85
pushInstructionFunction · 0.85
findOffsetFunction · 0.85
containsFunction · 0.85
createStackLayoutFunction · 0.85
atMethod · 0.80
allowsJunkMethod · 0.80
runMethod · 0.45
evmVersionMethod · 0.45
sizeMethod · 0.45
emptyMethod · 0.45

Tested by

no test coverage detected