Skip to content

Commit d384664

Browse files
authored
Merge pull request #11615 from ethereum/yulStackLayoutGenerator
Yul Stack Layout Generator (New Code Transform Step 2)
2 parents 7f137d3 + f881409 commit d384664

19 files changed

+2237
-22
lines changed

libsolutil/CommonData.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,21 @@ template <class T, class U> std::vector<T>& operator+=(std::vector<T>& _a, U&& _
5252
std::move(_b.begin(), _b.end(), std::back_inserter(_a));
5353
return _a;
5454
}
55+
56+
/// Concatenate the contents of a container onto a list
57+
template <class T, class U> std::list<T>& operator+=(std::list<T>& _a, U& _b)
58+
{
59+
for (auto const& i: _b)
60+
_a.push_back(T(i));
61+
return _a;
62+
}
63+
/// Concatenate the contents of a container onto a list, move variant.
64+
template <class T, class U> std::list<T>& operator+=(std::list<T>& _a, U&& _b)
65+
{
66+
std::move(_b.begin(), _b.end(), std::back_inserter(_a));
67+
return _a;
68+
}
69+
5570
/// Concatenate the contents of a container onto a multiset
5671
template <class U, class... T> std::multiset<T...>& operator+=(std::multiset<T...>& _a, U& _b)
5772
{
@@ -321,6 +336,44 @@ void joinMap(std::map<K, V>& _a, std::map<K, V>&& _b, F _conflictSolver)
321336
}
322337
}
323338

339+
namespace detail
340+
{
341+
342+
template<typename Container, typename Value>
343+
auto findOffset(Container&& _container, Value&& _value, int)
344+
-> decltype(_container.find(_value) == _container.end(), std::distance(_container.begin(), _container.find(_value)), std::optional<size_t>())
345+
{
346+
auto it = _container.find(std::forward<Value>(_value));
347+
auto end = _container.end();
348+
if (it == end)
349+
return std::nullopt;
350+
return std::distance(_container.begin(), it);
351+
}
352+
template<typename Range, typename Value>
353+
auto findOffset(Range&& _range, Value&& _value, void*)
354+
-> decltype(std::find(std::begin(_range), std::end(_range), std::forward<Value>(_value)) == std::end(_range), std::optional<size_t>())
355+
{
356+
auto begin = std::begin(_range);
357+
auto end = std::end(_range);
358+
auto it = std::find(begin, end, std::forward<Value>(_value));
359+
if (it == end)
360+
return std::nullopt;
361+
return std::distance(begin, it);
362+
}
363+
364+
}
365+
366+
/// @returns an std::optional<size_t> containing the offset of the first element in @a _range that is equal to @a _value,
367+
/// if any, or std::nullopt otherwise.
368+
/// Uses a linear search (``std::find``) unless @a _range is a container and provides a
369+
/// suitable ``.find`` function (e.g. it will use the logarithmic ``.find`` function in ``std::set`` instead).
370+
template<typename Range>
371+
auto findOffset(Range&& _range, std::remove_reference_t<decltype(*std::cbegin(_range))> const& _value)
372+
-> decltype(detail::findOffset(std::forward<Range>(_range), _value, 0))
373+
{
374+
return detail::findOffset(std::forward<Range>(_range), _value, 0);
375+
}
376+
324377
// String conversion functions, mainly to/from hex/nibble/byte representations.
325378

326379
enum class WhenError

libyul/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ add_library(yul
6868
backends/evm/EVMMetrics.h
6969
backends/evm/NoOutputAssembly.h
7070
backends/evm/NoOutputAssembly.cpp
71+
backends/evm/StackHelpers.h
72+
backends/evm/StackLayoutGenerator.h
73+
backends/evm/StackLayoutGenerator.cpp
7174
backends/evm/VariableReferenceCounter.h
7275
backends/evm/VariableReferenceCounter.cpp
7376
backends/wasm/EVMToEwasmTranslator.cpp

libyul/backends/evm/ControlFlowGraph.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <libyul/AST.h>
2525
#include <libyul/AsmAnalysisInfo.h>
2626
#include <libyul/Dialect.h>
27+
#include <libyul/Exceptions.h>
2728
#include <libyul/Scope.h>
2829

2930
#include <functional>
@@ -54,8 +55,19 @@ struct FunctionCallReturnLabelSlot
5455
/// the function.
5556
struct FunctionReturnLabelSlot
5657
{
57-
bool operator==(FunctionReturnLabelSlot const&) const { return true; }
58-
bool operator<(FunctionReturnLabelSlot const&) const { return false; }
58+
std::reference_wrapper<Scope::Function const> function;
59+
bool operator==(FunctionReturnLabelSlot const& _rhs) const
60+
{
61+
// There can never be return label slots of different functions on stack simultaneously.
62+
yulAssert(&function.get() == &_rhs.function.get(), "");
63+
return true;
64+
}
65+
bool operator<(FunctionReturnLabelSlot const& _rhs) const
66+
{
67+
// There can never be return label slots of different functions on stack simultaneously.
68+
yulAssert(&function.get() == &_rhs.function.get(), "");
69+
return false;
70+
}
5971
static constexpr bool canBeFreelyGenerated = false;
6072
};
6173
/// A slot containing the current value of a particular variable.

0 commit comments

Comments
 (0)