/* This file is part of solidity. solidity is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. solidity is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with solidity. If not, see . */ // SPDX-License-Identifier: GPL-3.0 /** * @author Alex Beregszaszi * Removes unused JUMPDESTs. */ #include #include #include using namespace solidity; using namespace solidity::util; using namespace solidity::evmasm; bool JumpdestRemover::optimise(std::set const& _tagsReferencedFromOutside) { std::set references{referencedTags(m_items, std::numeric_limits::max())}; references.insert(_tagsReferencedFromOutside.begin(), _tagsReferencedFromOutside.end()); size_t initialSize = m_items.size(); /// Remove tags which are never referenced. auto pend = remove_if( m_items.begin(), m_items.end(), [&](AssemblyItem const& _item) { if (_item.type() != Tag) return false; auto asmIdAndTag = _item.splitForeignPushTag(); assertThrow(asmIdAndTag.first == std::numeric_limits::max(), OptimizerException, "Sub-assembly tag used as label."); size_t tag = asmIdAndTag.second; return !references.count(tag); } ); m_items.erase(pend, m_items.end()); return m_items.size() != initialSize; } std::set JumpdestRemover::referencedTags(AssemblyItems const& _items, size_t _subId) { std::set ret; for (auto const& item: _items) if (item.type() == PushTag) { auto subAndTag = item.splitForeignPushTag(); if (subAndTag.first == _subId) ret.insert(subAndTag.second); } return ret; }