/src/solidity/libsolutil/Algorithms.h
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | #pragma once |
19 | | |
20 | | |
21 | | #include <functional> |
22 | | #include <list> |
23 | | #include <set> |
24 | | |
25 | | namespace solidity::util |
26 | | { |
27 | | |
28 | | /** |
29 | | * Detector for cycles in directed graphs. It returns the first |
30 | | * vertex on the path towards a cycle or a nullptr if there is |
31 | | * no reachable cycle starting from a given vertex. |
32 | | */ |
33 | | template <typename V> |
34 | | class CycleDetector |
35 | | { |
36 | | public: |
37 | | using Visitor = std::function<void(V const&, CycleDetector&, size_t)>; |
38 | | |
39 | | /// Initializes the cycle detector |
40 | | /// @param _visit function that is given the current vertex |
41 | | /// and is supposed to call @a run on all |
42 | | /// adjacent vertices. |
43 | | explicit CycleDetector(Visitor _visit): |
44 | | m_visit(std::move(_visit)) |
45 | | { } |
46 | | |
47 | | /// Recursively perform cycle detection starting |
48 | | /// (or continuing) with @param _vertex |
49 | | /// @returns the first vertex on the path towards a cycle from @a _vertex |
50 | | /// or nullptr if no cycle is reachable from @a _vertex. |
51 | | V const* run(V const& _vertex) |
52 | | { |
53 | | if (m_firstCycleVertex) |
54 | | return m_firstCycleVertex; |
55 | | if (m_processed.count(&_vertex)) |
56 | | return nullptr; |
57 | | else if (m_processing.count(&_vertex)) |
58 | | return m_firstCycleVertex = &_vertex; |
59 | | m_processing.insert(&_vertex); |
60 | | |
61 | | m_depth++; |
62 | | m_visit(_vertex, *this, m_depth); |
63 | | m_depth--; |
64 | | if (m_firstCycleVertex && m_depth == 1) |
65 | | m_firstCycleVertex = &_vertex; |
66 | | |
67 | | m_processing.erase(&_vertex); |
68 | | m_processed.insert(&_vertex); |
69 | | return m_firstCycleVertex; |
70 | | } |
71 | | |
72 | | private: |
73 | | Visitor m_visit; |
74 | | std::set<V const*> m_processing; |
75 | | std::set<V const*> m_processed; |
76 | | size_t m_depth = 0; |
77 | | V const* m_firstCycleVertex = nullptr; |
78 | | }; |
79 | | |
80 | | /** |
81 | | * Generic breadth first search. |
82 | | * |
83 | | * Note that V needs to be a comparable value type or a pointer. |
84 | | * |
85 | | * Example: Gather all (recursive) children in a graph starting at (and including) ``root``: |
86 | | * |
87 | | * Node const* root = ...; |
88 | | * std::set<Node const*> allNodes = BreadthFirstSearch<Node const*>{{root}}.run([](Node const* _node, auto&& _addChild) { |
89 | | * // Potentially process ``_node``. |
90 | | * for (Node const& _child: _node->children()) |
91 | | * // Potentially filter the children to be visited. |
92 | | * _addChild(&_child); |
93 | | * }).visited; |
94 | | */ |
95 | | template<typename V> |
96 | | struct BreadthFirstSearch |
97 | | { |
98 | | /// Runs the breadth first search. The verticesToTraverse member of the struct needs to be initialized. |
99 | | /// @param _forEachChild is a callable of the form [...](V const& _node, auto&& _addChild) { ... } |
100 | | /// that is called for each visited node and is supposed to call _addChild(childNode) for every child |
101 | | /// node of _node. |
102 | | template<typename ForEachChild> |
103 | | BreadthFirstSearch& run(ForEachChild&& _forEachChild) |
104 | 594k | { |
105 | 3.30M | while (!verticesToTraverse.empty()) |
106 | 2.70M | { |
107 | 2.70M | V v = std::move(verticesToTraverse.front()); |
108 | 2.70M | verticesToTraverse.pop_front(); |
109 | | |
110 | 2.70M | if (!visited.insert(v).second) |
111 | 387k | continue; |
112 | | |
113 | 2.31M | _forEachChild(v, [this](V _vertex) { |
114 | 2.09M | verticesToTraverse.emplace_back(std::move(_vertex)); |
115 | 2.09M | }); StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4>(solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 132k | _forEachChild(v, [this](V _vertex) { | 114 | 132k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 132k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10>(solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 197k | _forEachChild(v, [this](V _vertex) { | 114 | 197k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 197k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11>(solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 170k | _forEachChild(v, [this](V _vertex) { | 114 | 170k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 170k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14>(solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 170k | _forEachChild(v, [this](V _vertex) { | 114 | 170k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 170k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 197k | _forEachChild(v, [this](V _vertex) { | 114 | 197k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 197k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 25.1k | _forEachChild(v, [this](V _vertex) { | 114 | 25.1k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 25.1k | }); |
CircularReferencesPruner.cpp:solidity::util::BreadthFirstSearch<solidity::yul::YulString>::run<solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0>(solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0&&)::{lambda(solidity::yul::YulString)#1}::operator()(solidity::yul::YulString) const Line | Count | Source | 113 | 759k | _forEachChild(v, [this](V _vertex) { | 114 | 759k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 759k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16>((anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16&&)::{lambda(solidity::yul::CFG::BasicBlock*)#1}::operator()(solidity::yul::CFG::BasicBlock*) const Line | Count | Source | 113 | 197k | _forEachChild(v, [this](V _vertex) { | 114 | 197k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 197k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}&&)::{lambda(solidity::yul::CFG::BasicBlock*)#1}::operator()(solidity::yul::CFG::BasicBlock*) const Line | Count | Source | 113 | 117k | _forEachChild(v, [this](V _vertex) { | 114 | 117k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 117k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::FunctionCall*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18&&)::{lambda(solidity::yul::CFG::FunctionCall*)#1}::operator()(solidity::yul::CFG::FunctionCall*) const Line | Count | Source | 113 | 2.90k | _forEachChild(v, [this](V _vertex) { | 114 | 2.90k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 2.90k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20>((anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20&&)::{lambda(solidity::yul::CFG::BasicBlock*)#1}::operator()(solidity::yul::CFG::BasicBlock*) const Line | Count | Source | 113 | 120k | _forEachChild(v, [this](V _vertex) { | 114 | 120k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 120k | }); |
|
116 | 2.31M | } |
117 | 594k | return *this; |
118 | 594k | } StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4>(solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4&&) Line | Count | Source | 104 | 32.3k | { | 105 | 196k | while (!verticesToTraverse.empty()) | 106 | 164k | { | 107 | 164k | V v = std::move(verticesToTraverse.front()); | 108 | 164k | verticesToTraverse.pop_front(); | 109 | | | 110 | 164k | if (!visited.insert(v).second) | 111 | 14.9k | continue; | 112 | | | 113 | 149k | _forEachChild(v, [this](V _vertex) { | 114 | 149k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 149k | }); | 116 | 149k | } | 117 | 32.3k | return *this; | 118 | 32.3k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10>(solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10&&) Line | Count | Source | 104 | 41.2k | { | 105 | 280k | while (!verticesToTraverse.empty()) | 106 | 238k | { | 107 | 238k | V v = std::move(verticesToTraverse.front()); | 108 | 238k | verticesToTraverse.pop_front(); | 109 | | | 110 | 238k | if (!visited.insert(v).second) | 111 | 40.0k | continue; | 112 | | | 113 | 198k | _forEachChild(v, [this](V _vertex) { | 114 | 198k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 198k | }); | 116 | 198k | } | 117 | 41.2k | return *this; | 118 | 41.2k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11>(solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11&&) Line | Count | Source | 104 | 41.2k | { | 105 | 252k | while (!verticesToTraverse.empty()) | 106 | 211k | { | 107 | 211k | V v = std::move(verticesToTraverse.front()); | 108 | 211k | verticesToTraverse.pop_front(); | 109 | | | 110 | 211k | if (!visited.insert(v).second) | 111 | 12.4k | continue; | 112 | | | 113 | 198k | _forEachChild(v, [this](V _vertex) { | 114 | 198k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 198k | }); | 116 | 198k | } | 117 | 41.2k | return *this; | 118 | 41.2k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14>(solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14&&) Line | Count | Source | 104 | 41.2k | { | 105 | 252k | while (!verticesToTraverse.empty()) | 106 | 211k | { | 107 | 211k | V v = std::move(verticesToTraverse.front()); | 108 | 211k | verticesToTraverse.pop_front(); | 109 | | | 110 | 211k | if (!visited.insert(v).second) | 111 | 12.4k | continue; | 112 | | | 113 | 198k | _forEachChild(v, [this](V _vertex) { | 114 | 198k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 198k | }); | 116 | 198k | } | 117 | 41.2k | return *this; | 118 | 41.2k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17&&) Line | Count | Source | 104 | 41.2k | { | 105 | 280k | while (!verticesToTraverse.empty()) | 106 | 238k | { | 107 | 238k | V v = std::move(verticesToTraverse.front()); | 108 | 238k | verticesToTraverse.pop_front(); | 109 | | | 110 | 238k | if (!visited.insert(v).second) | 111 | 40.0k | continue; | 112 | | | 113 | 198k | _forEachChild(v, [this](V _vertex) { | 114 | 198k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 198k | }); | 116 | 198k | } | 117 | 41.2k | return *this; | 118 | 41.2k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}&&) Line | Count | Source | 104 | 8.33k | { | 105 | 41.8k | while (!verticesToTraverse.empty()) | 106 | 33.4k | { | 107 | 33.4k | V v = std::move(verticesToTraverse.front()); | 108 | 33.4k | verticesToTraverse.pop_front(); | 109 | | | 110 | 33.4k | if (!visited.insert(v).second) | 111 | 4.60k | continue; | 112 | | | 113 | 28.8k | _forEachChild(v, [this](V _vertex) { | 114 | 28.8k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 28.8k | }); | 116 | 28.8k | } | 117 | 8.33k | return *this; | 118 | 8.33k | } |
CircularReferencesPruner.cpp:solidity::util::BreadthFirstSearch<solidity::yul::YulString>& solidity::util::BreadthFirstSearch<solidity::yul::YulString>::run<solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0>(solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0&&) Line | Count | Source | 104 | 310k | { | 105 | 1.38M | while (!verticesToTraverse.empty()) | 106 | 1.07M | { | 107 | 1.07M | V v = std::move(verticesToTraverse.front()); | 108 | 1.07M | verticesToTraverse.pop_front(); | 109 | | | 110 | 1.07M | if (!visited.insert(v).second) | 111 | 174k | continue; | 112 | | | 113 | 895k | _forEachChild(v, [this](V _vertex) { | 114 | 895k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 895k | }); | 116 | 895k | } | 117 | 310k | return *this; | 118 | 310k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16>((anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16&&) Line | Count | Source | 104 | 20.7k | { | 105 | 259k | while (!verticesToTraverse.empty()) | 106 | 238k | { | 107 | 238k | V v = std::move(verticesToTraverse.front()); | 108 | 238k | verticesToTraverse.pop_front(); | 109 | | | 110 | 238k | if (!visited.insert(v).second) | 111 | 40.0k | continue; | 112 | | | 113 | 198k | _forEachChild(v, [this](V _vertex) { | 114 | 198k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 198k | }); | 116 | 198k | } | 117 | 20.7k | return *this; | 118 | 20.7k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}&&) Line | Count | Source | 104 | 20.5k | { | 105 | 158k | while (!verticesToTraverse.empty()) | 106 | 138k | { | 107 | 138k | V v = std::move(verticesToTraverse.front()); | 108 | 138k | verticesToTraverse.pop_front(); | 109 | | | 110 | 138k | if (!visited.insert(v).second) | 111 | 23.4k | continue; | 112 | | | 113 | 114k | _forEachChild(v, [this](V _vertex) { | 114 | 114k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 114k | }); | 116 | 114k | } | 117 | 20.5k | return *this; | 118 | 20.5k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::FunctionCall*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::FunctionCall*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18&&) Line | Count | Source | 104 | 13.2k | { | 105 | 28.9k | while (!verticesToTraverse.empty()) | 106 | 15.7k | { | 107 | 15.7k | V v = std::move(verticesToTraverse.front()); | 108 | 15.7k | verticesToTraverse.pop_front(); | 109 | | | 110 | 15.7k | if (!visited.insert(v).second) | 111 | 1.40k | continue; | 112 | | | 113 | 14.3k | _forEachChild(v, [this](V _vertex) { | 114 | 14.3k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 14.3k | }); | 116 | 14.3k | } | 117 | 13.2k | return *this; | 118 | 13.2k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20>((anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20&&) Line | Count | Source | 104 | 23.7k | { | 105 | 168k | while (!verticesToTraverse.empty()) | 106 | 144k | { | 107 | 144k | V v = std::move(verticesToTraverse.front()); | 108 | 144k | verticesToTraverse.pop_front(); | 109 | | | 110 | 144k | if (!visited.insert(v).second) | 111 | 23.6k | continue; | 112 | | | 113 | 120k | _forEachChild(v, [this](V _vertex) { | 114 | 120k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 120k | }); | 116 | 120k | } | 117 | 23.7k | return *this; | 118 | 23.7k | } |
|
119 | | void abort() |
120 | 908 | { |
121 | 908 | verticesToTraverse.clear(); |
122 | 908 | } |
123 | | |
124 | | std::list<V> verticesToTraverse; |
125 | | std::set<V> visited{}; |
126 | | }; |
127 | | |
128 | | } |