mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge remote-tracking branch 'origin/develop' into develop_060
Had to adjust gas costs during merge.
This commit is contained in:
commit
f3c4f466f6
@ -190,7 +190,7 @@ defaults:
|
||||
-i -H "Content-Type: application/json"
|
||||
-H "Accept: application/json"
|
||||
-H "Authorization: Bearer $GITTER_API_TOKEN" "https://api.gitter.im/v1/rooms/$GITTER_NOTIFY_ROOM_ID/chatMessages"
|
||||
-d '{"text":" ❌ Nightly job **'$CIRCLE_JOB'** failed. Please check '$CIRCLE_BUILD_URL' for details."}'
|
||||
-d '{"text":" ❌ Nightly job **'$CIRCLE_JOB'** failed on **'$CIRCLE_BRANCH'**. Please see '$CIRCLE_BUILD_URL' for details."}'
|
||||
when: on_fail
|
||||
|
||||
- gitter_notify_success: &gitter_notify_success
|
||||
@ -200,7 +200,7 @@ defaults:
|
||||
-i -H "Content-Type: application/json"
|
||||
-H "Accept: application/json"
|
||||
-H "Authorization: Bearer $GITTER_API_TOKEN" "https://api.gitter.im/v1/rooms/$GITTER_NOTIFY_ROOM_ID/chatMessages"
|
||||
-d '{"text":" ✅ Nightly job **'$CIRCLE_JOB'** succeeded. Please check '$CIRCLE_BUILD_URL' for details."}'
|
||||
-d '{"text":" ✅ Nightly job **'$CIRCLE_JOB'** succeeded on **'$CIRCLE_BRANCH'**. Please see '$CIRCLE_BUILD_URL' for details."}'
|
||||
when: on_success
|
||||
|
||||
# -----------------------------------------------------------------------------------------------
|
||||
@ -656,6 +656,7 @@ workflows:
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
- develop_060
|
||||
|
||||
jobs:
|
||||
# Emscripten builds and external tests
|
||||
|
131
.circleci/docker/Dockerfile.clang.ubuntu1904
Normal file
131
.circleci/docker/Dockerfile.clang.ubuntu1904
Normal file
@ -0,0 +1,131 @@
|
||||
# vim:syntax=dockerfile
|
||||
#------------------------------------------------------------------------------
|
||||
# Dockerfile for building and testing Solidity Compiler on CI
|
||||
# Target: Ubuntu 19.04 (Disco Dingo) Clang variant
|
||||
# URL: https://hub.docker.com/r/ethereum/solidity-buildpack-deps
|
||||
#
|
||||
# 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 <http://www.gnu.org/licenses/>
|
||||
#
|
||||
# (c) 2016-2019 solidity contributors.
|
||||
#------------------------------------------------------------------------------
|
||||
FROM buildpack-deps:disco AS base
|
||||
|
||||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN set -ex; \
|
||||
dist=$(grep DISTRIB_CODENAME /etc/lsb-release | cut -d= -f2); \
|
||||
echo "deb http://ppa.launchpad.net/ethereum/cpp-build-deps/ubuntu $dist main" >> /etc/apt/sources.list ; \
|
||||
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 1c52189c923f6ca9 ; \
|
||||
apt-get update; \
|
||||
apt-get install -qqy --no-install-recommends \
|
||||
build-essential \
|
||||
software-properties-common \
|
||||
cmake ninja-build \
|
||||
clang++-8 llvm-8-dev \
|
||||
libjsoncpp-dev \
|
||||
libleveldb1d \
|
||||
; \
|
||||
apt-get install -qy python-pip python-sphinx; \
|
||||
update-alternatives --install /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-8 1; \
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-8 1; \
|
||||
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-8 1; \
|
||||
pip install codecov; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
FROM base AS libraries
|
||||
|
||||
ENV CC clang
|
||||
ENV CXX clang++
|
||||
|
||||
# Boost
|
||||
RUN git clone --recursive -b boost-1.69.0 https://github.com/boostorg/boost.git \
|
||||
/usr/src/boost; \
|
||||
cd /usr/src/boost; \
|
||||
./bootstrap.sh --with-toolset=clang --prefix=/usr; \
|
||||
./b2 toolset=clang headers; \
|
||||
./b2 toolset=clang variant=release \
|
||||
system regex filesystem unit_test_framework program_options \
|
||||
install -j $(($(nproc)/2)); \
|
||||
rm -rf /usr/src/boost
|
||||
|
||||
# Z3
|
||||
RUN git clone --depth 1 -b Z3-4.8.5 https://github.com/Z3Prover/z3.git \
|
||||
/usr/src/z3; \
|
||||
cd /usr/src/z3; \
|
||||
python scripts/mk_make.py --prefix=/usr ; \
|
||||
cd build; \
|
||||
make -j; \
|
||||
make install; \
|
||||
rm -rf /usr/src/z3;
|
||||
|
||||
# OSSFUZZ: libprotobuf-mutator
|
||||
RUN set -ex; \
|
||||
git clone https://github.com/google/libprotobuf-mutator.git \
|
||||
/usr/src/libprotobuf-mutator; \
|
||||
cd /usr/src/libprotobuf-mutator; \
|
||||
git checkout d1fe8a7d8ae18f3d454f055eba5213c291986f21; \
|
||||
mkdir build; \
|
||||
cd build; \
|
||||
cmake .. -GNinja -DLIB_PROTO_MUTATOR_DOWNLOAD_PROTOBUF=ON \
|
||||
-DLIB_PROTO_MUTATOR_TESTING=OFF -DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr"; \
|
||||
ninja; \
|
||||
cp -vpr external.protobuf/bin/* /usr/bin/; \
|
||||
cp -vpr external.protobuf/include/* /usr/include/; \
|
||||
cp -vpr external.protobuf/lib/* /usr/lib/; \
|
||||
ninja install/strip; \
|
||||
rm -rf /usr/src/libprotobuf-mutator
|
||||
|
||||
# ETHASH
|
||||
RUN set -ex; \
|
||||
cd /usr/src; \
|
||||
git clone --branch="v0.4.4" https://github.com/chfast/ethash.git; \
|
||||
cd ethash; \
|
||||
mkdir build; \
|
||||
cd build; \
|
||||
cmake .. -G Ninja -DBUILD_SHARED_LIBS=ON -DETHASH_BUILD_TESTS=OFF -DCMAKE_INSTALL_PREFIX="/usr"; \
|
||||
ninja; \
|
||||
ninja install/strip; \
|
||||
rm -rf /usr/src/ethash
|
||||
|
||||
# INTX
|
||||
RUN set -ex; \
|
||||
cd /usr/src; \
|
||||
git clone --branch="v0.2.0" https://github.com/chfast/intx.git; \
|
||||
cd intx; \
|
||||
mkdir build; \
|
||||
cd build; \
|
||||
cmake .. -G Ninja -DBUILD_SHARED_LIBS=ON -DINTX_TESTING=OFF -DINTX_BENCHMARKING=OFF -DCMAKE_INSTALL_PREFIX="/usr"; \
|
||||
ninja; \
|
||||
ninja install/strip; \
|
||||
rm -rf /usr/src/intx;
|
||||
|
||||
# EVMONE
|
||||
RUN set -ex; \
|
||||
cd /usr/src; \
|
||||
git clone --branch="v0.1.0" --recurse-submodules https://github.com/ethereum/evmone.git; \
|
||||
cd evmone; \
|
||||
mkdir build; \
|
||||
cd build; \
|
||||
cmake -G Ninja -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX="/usr" ..; \
|
||||
ninja; \
|
||||
ninja install/strip; \
|
||||
rm -rf /usr/src/evmone
|
||||
|
||||
FROM base
|
||||
COPY --from=libraries /usr/lib /usr/lib
|
||||
COPY --from=libraries /usr/bin /usr/bin
|
||||
COPY --from=libraries /usr/include /usr/include
|
@ -44,6 +44,7 @@ Compiler Features:
|
||||
|
||||
Bugfixes:
|
||||
* Fix internal error when popping a dynamic storage array of mappings.
|
||||
* Yul Optimizer: Fix reordering bug in connection with shifted one and mul/div-instructions in for loop conditions.
|
||||
|
||||
|
||||
### 0.5.11 (2019-08-12)
|
||||
|
@ -1,9 +1,11 @@
|
||||
# Inherit default options
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/default.cmake")
|
||||
# Disable Z3 and CVC4 since none of the existing fuzzers need them
|
||||
set(USE_Z3 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_CVC4 OFF CACHE BOOL "" FORCE)
|
||||
set(USE_Z3 OFF CACHE BOOL "Disable Z3" FORCE)
|
||||
set(USE_CVC4 OFF CACHE BOOL "Disable CVC4" FORCE)
|
||||
# Build fuzzing binaries
|
||||
set(OSSFUZZ 1)
|
||||
set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE)
|
||||
# Use libfuzzer as the fuzzing back-end
|
||||
set(LIB_FUZZING_ENGINE "-fsanitize=fuzzer" CACHE STRING "Use libfuzzer back-end" FORCE)
|
||||
# clang/libfuzzer specific flags for ASan instrumentation
|
||||
set(CMAKE_CXX_FLAGS "-O1 -gline-tables-only -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -stdlib=libstdc++")
|
||||
set(CMAKE_CXX_FLAGS "-O1 -gline-tables-only -fsanitize=address -fsanitize-address-use-after-scope -fsanitize=fuzzer-no-link -stdlib=libstdc++" CACHE STRING "Custom compilation flags" FORCE)
|
||||
|
11
cmake/toolchains/ossfuzz.cmake
Normal file
11
cmake/toolchains/ossfuzz.cmake
Normal file
@ -0,0 +1,11 @@
|
||||
# Inherit default options
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/default.cmake")
|
||||
# Disable CVC4.
|
||||
set(USE_CVC4 OFF CACHE BOOL "Disable CVC4" FORCE)
|
||||
# Enable fuzzers
|
||||
set(OSSFUZZ ON CACHE BOOL "Enable fuzzer build" FORCE)
|
||||
set(LIB_FUZZING_ENGINE $ENV{LIB_FUZZING_ENGINE} CACHE STRING "Use fuzzer back-end defined by environment variable" FORCE)
|
||||
# Link statically against boost libraries
|
||||
set(BOOST_FOUND ON CACHE BOOL "" FORCE)
|
||||
set(Boost_USE_STATIC_LIBS ON CACHE BOOL "Link against static Boost libraries" FORCE)
|
||||
set(Boost_USE_STATIC_RUNTIME ON CACHE BOOL "Link against static Boost runtime library" FORCE)
|
@ -163,7 +163,8 @@ If an opcode takes arguments (always from the top of the stack), they are given
|
||||
Note that the order of arguments can be seen to be reversed in non-functional style (explained below).
|
||||
Opcodes marked with ``-`` do not push an item onto the stack (do not return a result),
|
||||
those marked with ``*`` are special and all others push exactly one item onto the stack (their "return value").
|
||||
Opcodes marked with ``F``, ``H``, ``B`` or ``C`` are present since Frontier, Homestead, Byzantium or Constantinople, respectively.
|
||||
Opcodes marked with ``F``, ``H``, ``B``, ``C`` or ``I`` are present since Frontier, Homestead,
|
||||
Byzantium, Constantinople or Istanbul, respectively.
|
||||
|
||||
In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to
|
||||
but not including position ``b`` and ``storage[p]`` signifies the storage contents at position ``p``.
|
||||
@ -259,6 +260,8 @@ In the grammar, opcodes are represented as pre-defined identifiers.
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| balance(a) | | F | wei balance at address a |
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| selfbalance() | | I | equivalent to balance(address()), but cheaper |
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| caller | | F | call sender (excluding ``delegatecall``) |
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| callvalue | | F | wei sent together with the current call |
|
||||
@ -325,6 +328,8 @@ In the grammar, opcodes are represented as pre-defined identifiers.
|
||||
| log4(p, s, t1, t2, t3, | `-` | F | log with topics t1, t2, t3, t4 and data mem[p...(p+s)) |
|
||||
| t4) | | | |
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| chainid | | I | ID of the executing chain (EIP 1344) |
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| origin | | F | transaction sender |
|
||||
+-------------------------+-----+---+-----------------------------------------------------------------+
|
||||
| gasprice | | F | gas price of the transaction |
|
||||
|
@ -254,6 +254,61 @@ if you want all overflows to cause a revert.
|
||||
|
||||
Code such as ``require((balanceOf[_to] + _value) >= balanceOf[_to])`` can also help you check if values are what you expect.
|
||||
|
||||
.. _clearing-mappings:
|
||||
|
||||
Clearing Mappings
|
||||
=================
|
||||
|
||||
The Solidity type ``mapping`` (see :ref:`mapping-types`) is a storage-only key-value data structure that
|
||||
does not keep track of the keys that were assigned a non-zero value.
|
||||
Because of that, cleaning a mapping without extra information about the written
|
||||
keys is not possible.
|
||||
If a ``mapping`` is used as the base type of a dynamic storage array, deleting
|
||||
or popping the array will have no effect over the ``mapping`` elements.
|
||||
The same happens, for example, if a ``mapping`` is used as the type of a member
|
||||
field of a ``struct`` that is the base type of a dynamic storage array.
|
||||
The ``mapping`` is also ignored in assignments of structs or arrays containing
|
||||
a ``mapping``.
|
||||
|
||||
::
|
||||
|
||||
pragma solidity >=0.5.0 <0.7.0;
|
||||
|
||||
contract Map {
|
||||
mapping (uint => uint)[] array;
|
||||
|
||||
function allocate(uint _newMaps) public {
|
||||
array.length += _newMaps;
|
||||
}
|
||||
|
||||
function writeMap(uint _map, uint _key, uint _value) public {
|
||||
array[_map][_key] = _value;
|
||||
}
|
||||
|
||||
function readMap(uint _map, uint _key) public view returns (uint) {
|
||||
return array[_map][_key];
|
||||
}
|
||||
|
||||
function eraseMaps() public {
|
||||
delete array;
|
||||
}
|
||||
}
|
||||
|
||||
Consider the example above and the following sequence of calls: ``allocate(10)``,
|
||||
``writeMap(4, 128, 256)``.
|
||||
At this point, calling ``readMap(4, 128)`` returns 256.
|
||||
If we call ``eraseMaps``, the length of state variable ``array`` is zeroed, but
|
||||
since its ``mapping`` elements cannot be zeroed, their information stays alive
|
||||
in the contract's storage.
|
||||
After deleting ``array``, calling ``allocate(5)`` allows us to access
|
||||
``array[4]`` again, and calling ``readMap(4, 128)`` returns 256 even without
|
||||
another call to ``writeMap``.
|
||||
|
||||
If your ``mapping`` information must be deleted, consider using a library similar to
|
||||
`iterable mapping <https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol>`_,
|
||||
allowing you to traverse the keys and delete their values in the appropriate
|
||||
``mapping``.
|
||||
|
||||
Minor Details
|
||||
=============
|
||||
|
||||
|
@ -17,7 +17,8 @@ byte-representation is all zeros, a type's :ref:`default value <default-value>`.
|
||||
mapping, only its ``keccak256`` hash is used to look up the value.
|
||||
|
||||
Because of this, mappings do not have a length or a concept of a key or
|
||||
value being set.
|
||||
value being set, and therefore cannot be erased without extra information
|
||||
regarding the assigned keys (see :ref:`clearing-mappings`).
|
||||
|
||||
Mappings can only have a data location of ``storage`` and thus
|
||||
are allowed for state variables, as storage reference types
|
||||
|
@ -122,7 +122,8 @@ at each version. Backward compatibility is not guaranteed between each version.
|
||||
- Shifting operators use shifting opcodes and thus need less gas.
|
||||
- ``petersburg`` (**default**)
|
||||
- The compiler behaves the same way as with constantinople.
|
||||
- ``istanbul`` (**experimental**)
|
||||
- ``istanbul``
|
||||
- Opcodes ``chainid`` and ``selfbalance`` are available in assembly.
|
||||
- ``berlin`` (**experimental**)
|
||||
|
||||
|
||||
|
@ -98,6 +98,14 @@ inline std::set<T> operator+(std::set<T>&& _a, U&& _b)
|
||||
ret += std::forward<U>(_b);
|
||||
return ret;
|
||||
}
|
||||
/// Remove one set from another one.
|
||||
template <class T>
|
||||
inline std::set<T>& operator-=(std::set<T>& _a, std::set<T> const& _b)
|
||||
{
|
||||
for (auto const& x: _b)
|
||||
_a.erase(x);
|
||||
return _a;
|
||||
}
|
||||
|
||||
namespace dev
|
||||
{
|
||||
|
@ -475,7 +475,8 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
|
||||
[=]() -> Pattern {
|
||||
return {Instruction::SHL, {Y, X}};
|
||||
},
|
||||
false
|
||||
// Actually only changes the order, does not remove.
|
||||
true
|
||||
});
|
||||
rules.push_back({
|
||||
// MUL(SHL(X, 1), Y) -> SHL(X, Y)
|
||||
@ -492,7 +493,8 @@ std::vector<SimplificationRule<Pattern>> simplificationRuleListPart7(
|
||||
[=]() -> Pattern {
|
||||
return {Instruction::SHR, {Y, X}};
|
||||
},
|
||||
false
|
||||
// Actually only changes the order, does not remove.
|
||||
true
|
||||
});
|
||||
|
||||
std::function<bool()> feasibilityFunction = [=]() {
|
||||
|
@ -88,6 +88,8 @@ add_library(yul
|
||||
optimiser/ExpressionSplitter.h
|
||||
optimiser/ForLoopConditionIntoBody.cpp
|
||||
optimiser/ForLoopConditionIntoBody.h
|
||||
optimiser/ForLoopConditionOutOfBody.cpp
|
||||
optimiser/ForLoopConditionOutOfBody.h
|
||||
optimiser/ForLoopInitRewriter.cpp
|
||||
optimiser/ForLoopInitRewriter.h
|
||||
optimiser/FullInliner.cpp
|
||||
|
69
libyul/optimiser/ForLoopConditionOutOfBody.cpp
Normal file
69
libyul/optimiser/ForLoopConditionOutOfBody.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/optimiser/Semantics.h>
|
||||
#include <libyul/AsmData.h>
|
||||
#include <libyul/Utilities.h>
|
||||
#include <libdevcore/CommonData.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
using namespace yul;
|
||||
|
||||
void ForLoopConditionOutOfBody::operator()(ForLoop& _forLoop)
|
||||
{
|
||||
ASTModifier::operator()(_forLoop);
|
||||
|
||||
if (
|
||||
!m_dialect.booleanNegationFunction() ||
|
||||
_forLoop.condition->type() != typeid(Literal) ||
|
||||
valueOfLiteral(boost::get<Literal>(*_forLoop.condition)) == u256(0) ||
|
||||
_forLoop.body.statements.empty() ||
|
||||
_forLoop.body.statements.front().type() != typeid(If)
|
||||
)
|
||||
return;
|
||||
|
||||
If& firstStatement = boost::get<If>(_forLoop.body.statements.front());
|
||||
if (
|
||||
firstStatement.body.statements.empty() ||
|
||||
firstStatement.body.statements.front().type() != typeid(Break)
|
||||
)
|
||||
return;
|
||||
if (!SideEffectsCollector(m_dialect, *firstStatement.condition).movable())
|
||||
return;
|
||||
|
||||
YulString iszero = m_dialect.booleanNegationFunction()->name;
|
||||
langutil::SourceLocation location = locationOf(*firstStatement.condition);
|
||||
|
||||
if (
|
||||
firstStatement.condition->type() == typeid(FunctionCall) &&
|
||||
boost::get<FunctionCall>(*firstStatement.condition).functionName.name == iszero
|
||||
)
|
||||
_forLoop.condition = make_unique<Expression>(std::move(boost::get<FunctionCall>(*firstStatement.condition).arguments.front()));
|
||||
else
|
||||
_forLoop.condition = make_unique<Expression>(FunctionCall{
|
||||
location,
|
||||
Identifier{location, iszero},
|
||||
make_vector<Expression>(
|
||||
std::move(*firstStatement.condition)
|
||||
)
|
||||
});
|
||||
|
||||
_forLoop.body.statements.erase(_forLoop.body.statements.begin());
|
||||
}
|
||||
|
69
libyul/optimiser/ForLoopConditionOutOfBody.h
Normal file
69
libyul/optimiser/ForLoopConditionOutOfBody.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <libyul/optimiser/ASTWalker.h>
|
||||
#include <libyul/Dialect.h>
|
||||
|
||||
namespace yul
|
||||
{
|
||||
|
||||
/**
|
||||
* Reverses the transformation of ForLoopConditionIntoBody.
|
||||
*
|
||||
* For any movable ``c``, it turns
|
||||
*
|
||||
* for { ... } 1 { ... } {
|
||||
* if iszero(c) { break }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* into
|
||||
*
|
||||
* for { ... } c { ... } {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* and it turns
|
||||
*
|
||||
* for { ... } 1 { ... } {
|
||||
* if c { break }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* into
|
||||
*
|
||||
* for { ... } iszero(c) { ... } {
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* The LiteralRematerialiser should be run before this step.
|
||||
*/
|
||||
class ForLoopConditionOutOfBody: public ASTModifier
|
||||
{
|
||||
public:
|
||||
ForLoopConditionOutOfBody(Dialect const& _dialect):
|
||||
m_dialect(_dialect)
|
||||
{}
|
||||
using ASTModifier::operator();
|
||||
void operator()(ForLoop& _forLoop) override;
|
||||
|
||||
private:
|
||||
Dialect const& m_dialect;
|
||||
};
|
||||
|
||||
}
|
@ -119,8 +119,9 @@ so that other components can more easily work with it. The final representation
|
||||
will be similar to a static-single-assignment (SSA) form, with the difference
|
||||
that it does not make use of explicit "phi" functions which combines the values
|
||||
from different branches of control flow because such a feature does not exist
|
||||
in the Yul language. Instead, assignments to existing variables are
|
||||
used.
|
||||
in the Yul language. Instead, when control flow merges, if a variable is re-assigned
|
||||
in one of the branches, a new SSA variable is declared to hold its current value,
|
||||
so that the following expressions still only need to reference SSA variables.
|
||||
|
||||
An example transformation is the following:
|
||||
|
||||
@ -139,21 +140,25 @@ as follows:
|
||||
|
||||
{
|
||||
let _1 := 0
|
||||
let a_1 := calldataload(_1)
|
||||
let a_9 := calldataload(_1)
|
||||
let a := a_9
|
||||
let _2 := 0x20
|
||||
let b_1 := calldataload(_2)
|
||||
let b := b_1
|
||||
let b_10 := calldataload(_2)
|
||||
let b := b_10
|
||||
let _3 := 0
|
||||
let _4 := gt(a_1, _3)
|
||||
if _4 {
|
||||
let _4 := gt(a_9, _3)
|
||||
if _4
|
||||
{
|
||||
let _5 := 0x20
|
||||
let b_2 := mul(b_1, _5)
|
||||
b := b_2
|
||||
let b_11 := mul(b_10, _5)
|
||||
b := b_11
|
||||
}
|
||||
let a_2 := add(a_1, 1)
|
||||
let _6 := 0x20
|
||||
let _7 := add(b, _6)
|
||||
sstore(a_2, _7)
|
||||
let b_12 := b
|
||||
let _6 := 1
|
||||
let a_13 := add(a_9, _6)
|
||||
let _7 := 0x20
|
||||
let _8 := add(b_12, _7)
|
||||
sstore(a_13, _8)
|
||||
}
|
||||
|
||||
Note that the only variable that is re-assigned in this snippet is ``b``.
|
||||
@ -240,6 +245,10 @@ reference to ``a`` by ``a_i``.
|
||||
The current value mapping is cleared for a variable ``a`` at the end of each block
|
||||
in which it was assigned to and at the end of the for loop init block if it is assigned
|
||||
inside the for loop body or post block.
|
||||
If a variable's value is cleared according to the rule above and the variable is declared outside
|
||||
the block, a new SSA variable will be created at the location where control flow joins,
|
||||
this includes the beginning of loop post/body block and the location right after
|
||||
If/Switch/ForLoop/Block statement.
|
||||
|
||||
After this stage, the Redundant Assign Eliminator is recommended to remove the unnecessary
|
||||
intermediate assignments.
|
||||
|
@ -50,8 +50,6 @@ public:
|
||||
|
||||
private:
|
||||
NameDispenser& m_nameDispenser;
|
||||
/// This is a set of all variables that are assigned to anywhere in the code.
|
||||
/// Variables that are only declared but never re-assigned are not touched.
|
||||
set<YulString> const& m_variablesToReplace;
|
||||
};
|
||||
|
||||
@ -130,7 +128,142 @@ void IntroduceSSA::operator()(Block& _block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Second step of SSA transform: Replace the references to variables-to-be-replaced
|
||||
* Second step of SSA transform: Introduces new SSA variables at each control-flow join
|
||||
* and at the beginning of functions.
|
||||
*/
|
||||
class IntroduceControlFlowSSA: public ASTModifier
|
||||
{
|
||||
public:
|
||||
explicit IntroduceControlFlowSSA(
|
||||
NameDispenser& _nameDispenser,
|
||||
set<YulString> const& _variablesToReplace
|
||||
):
|
||||
m_nameDispenser(_nameDispenser), m_variablesToReplace(_variablesToReplace)
|
||||
{ }
|
||||
|
||||
void operator()(FunctionDefinition& _function) override;
|
||||
void operator()(ForLoop& _forLoop) override;
|
||||
void operator()(Switch& _switch) override;
|
||||
void operator()(Block& _block) override;
|
||||
|
||||
private:
|
||||
NameDispenser& m_nameDispenser;
|
||||
set<YulString> const& m_variablesToReplace;
|
||||
/// Variables (that are to be replaced) currently in scope.
|
||||
set<YulString> m_variablesInScope;
|
||||
/// Set of variables that do not have a specific value.
|
||||
set<YulString> m_variablesToReassign;
|
||||
};
|
||||
|
||||
void IntroduceControlFlowSSA::operator()(FunctionDefinition& _function)
|
||||
{
|
||||
set<YulString> varsInScope;
|
||||
std::swap(varsInScope, m_variablesInScope);
|
||||
set<YulString> toReassign;
|
||||
std::swap(toReassign, m_variablesToReassign);
|
||||
|
||||
for (auto const& param: _function.parameters)
|
||||
if (m_variablesToReplace.count(param.name))
|
||||
{
|
||||
m_variablesInScope.insert(param.name);
|
||||
m_variablesToReassign.insert(param.name);
|
||||
}
|
||||
|
||||
ASTModifier::operator()(_function);
|
||||
|
||||
m_variablesInScope = std::move(varsInScope);
|
||||
m_variablesToReassign = std::move(toReassign);
|
||||
}
|
||||
|
||||
void IntroduceControlFlowSSA::operator()(ForLoop& _for)
|
||||
{
|
||||
(*this)(_for.pre);
|
||||
|
||||
Assignments assignments;
|
||||
assignments(_for.body);
|
||||
assignments(_for.post);
|
||||
|
||||
|
||||
for (auto const& var: assignments.names())
|
||||
if (m_variablesInScope.count(var))
|
||||
m_variablesToReassign.insert(var);
|
||||
|
||||
(*this)(_for.body);
|
||||
(*this)(_for.post);
|
||||
}
|
||||
|
||||
void IntroduceControlFlowSSA::operator()(Switch& _switch)
|
||||
{
|
||||
yulAssert(m_variablesToReassign.empty(), "");
|
||||
|
||||
set<YulString> toReassign;
|
||||
for (auto& c: _switch.cases)
|
||||
{
|
||||
(*this)(c.body);
|
||||
toReassign += m_variablesToReassign;
|
||||
}
|
||||
|
||||
m_variablesToReassign += toReassign;
|
||||
}
|
||||
|
||||
void IntroduceControlFlowSSA::operator()(Block& _block)
|
||||
{
|
||||
set<YulString> variablesDeclaredHere;
|
||||
set<YulString> assignedVariables;
|
||||
|
||||
iterateReplacing(
|
||||
_block.statements,
|
||||
[&](Statement& _s) -> boost::optional<vector<Statement>>
|
||||
{
|
||||
vector<Statement> toPrepend;
|
||||
for (YulString toReassign: m_variablesToReassign)
|
||||
{
|
||||
YulString newName = m_nameDispenser.newName(toReassign);
|
||||
toPrepend.emplace_back(VariableDeclaration{
|
||||
locationOf(_s),
|
||||
{TypedName{locationOf(_s), newName, {}}},
|
||||
make_unique<Expression>(Identifier{locationOf(_s), toReassign})
|
||||
});
|
||||
assignedVariables.insert(toReassign);
|
||||
}
|
||||
m_variablesToReassign.clear();
|
||||
|
||||
if (_s.type() == typeid(VariableDeclaration))
|
||||
{
|
||||
VariableDeclaration& varDecl = boost::get<VariableDeclaration>(_s);
|
||||
for (auto const& var: varDecl.variables)
|
||||
if (m_variablesToReplace.count(var.name))
|
||||
{
|
||||
variablesDeclaredHere.insert(var.name);
|
||||
m_variablesInScope.insert(var.name);
|
||||
}
|
||||
}
|
||||
else if (_s.type() == typeid(Assignment))
|
||||
{
|
||||
Assignment& assignment = boost::get<Assignment>(_s);
|
||||
for (auto const& var: assignment.variableNames)
|
||||
if (m_variablesToReplace.count(var.name))
|
||||
assignedVariables.insert(var.name);
|
||||
}
|
||||
else
|
||||
visit(_s);
|
||||
|
||||
if (toPrepend.empty())
|
||||
return {};
|
||||
else
|
||||
{
|
||||
toPrepend.emplace_back(std::move(_s));
|
||||
return toPrepend;
|
||||
}
|
||||
}
|
||||
);
|
||||
m_variablesToReassign += assignedVariables;
|
||||
m_variablesInScope -= variablesDeclaredHere;
|
||||
m_variablesToReassign -= variablesDeclaredHere;
|
||||
}
|
||||
|
||||
/**
|
||||
* Third step of SSA transform: Replace the references to variables-to-be-replaced
|
||||
* by their current values.
|
||||
*/
|
||||
class PropagateValues: public ASTModifier
|
||||
@ -166,13 +299,27 @@ void PropagateValues::operator()(VariableDeclaration& _varDecl)
|
||||
|
||||
if (_varDecl.variables.size() != 1)
|
||||
return;
|
||||
YulString name = _varDecl.variables.front().name;
|
||||
if (!m_variablesToReplace.count(name))
|
||||
return;
|
||||
|
||||
yulAssert(_varDecl.value->type() == typeid(Identifier), "");
|
||||
m_currentVariableValues[name] = boost::get<Identifier>(*_varDecl.value).name;
|
||||
m_clearAtEndOfBlock.insert(name);
|
||||
YulString variable = _varDecl.variables.front().name;
|
||||
if (m_variablesToReplace.count(variable))
|
||||
{
|
||||
// `let a := a_1` - regular declaration of non-SSA variable
|
||||
yulAssert(_varDecl.value->type() == typeid(Identifier), "");
|
||||
m_currentVariableValues[variable] = boost::get<Identifier>(*_varDecl.value).name;
|
||||
m_clearAtEndOfBlock.insert(variable);
|
||||
}
|
||||
else if (_varDecl.value && _varDecl.value->type() == typeid(Identifier))
|
||||
{
|
||||
// `let a_1 := a` - assignment to SSA variable after a branch.
|
||||
YulString value = boost::get<Identifier>(*_varDecl.value).name;
|
||||
if (m_variablesToReplace.count(value))
|
||||
{
|
||||
// This is safe because `a_1` is not a "variable to replace" and thus
|
||||
// will not be re-assigned.
|
||||
m_currentVariableValues[value] = variable;
|
||||
m_clearAtEndOfBlock.insert(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -186,7 +333,7 @@ void PropagateValues::operator()(Assignment& _assignment)
|
||||
if (!m_variablesToReplace.count(name))
|
||||
return;
|
||||
|
||||
yulAssert(_assignment.value->type() == typeid(Identifier), "");
|
||||
yulAssert(_assignment.value && _assignment.value->type() == typeid(Identifier), "");
|
||||
m_currentVariableValues[name] = boost::get<Identifier>(*_assignment.value).name;
|
||||
m_clearAtEndOfBlock.insert(name);
|
||||
}
|
||||
@ -231,6 +378,7 @@ void SSATransform::run(Block& _ast, NameDispenser& _nameDispenser)
|
||||
Assignments assignments;
|
||||
assignments(_ast);
|
||||
IntroduceSSA{_nameDispenser, assignments.names()}(_ast);
|
||||
IntroduceControlFlowSSA{_nameDispenser, assignments.names()}(_ast);
|
||||
PropagateValues{assignments.names()}(_ast);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include <libyul/AsmDataForward.h>
|
||||
#include <libyul/optimiser/ASTWalker.h>
|
||||
|
||||
#include <liblangutil/SourceLocation.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace yul
|
||||
@ -61,8 +63,10 @@ class NameDispenser;
|
||||
* Furthermore, always note the current variable/value assigned to a and replace each
|
||||
* reference to a by this variable.
|
||||
* The current value mapping is cleared for a variable a at the end of each block
|
||||
* in which it was assigned and just after the for loop init block if it is assigned
|
||||
* inside the for loop.
|
||||
* in which it was assigned. We compensate that by appending a declaration
|
||||
* of the form of "let a_1 := a" right after the location where control flow joins so
|
||||
* variable references can use the SSA variable. The only exception to this rule are
|
||||
* for loop conditions, as we cannot insert a variable declaration there.
|
||||
*
|
||||
* After this stage, redundantAssignmentRemover is recommended to remove the unnecessary
|
||||
* intermediate assignments.
|
||||
@ -70,7 +74,17 @@ class NameDispenser;
|
||||
* This stage provides best results if CSE is run right before it, because
|
||||
* then it does not generate excessive amounts of variables.
|
||||
*
|
||||
* The transform is implemented in three stages. All stages are only concerned
|
||||
* with variables that are assigned somewhere in the code (excluding declarations).
|
||||
* The first stage inserts new SSA variables for each declaration and assignment of
|
||||
* such variables.
|
||||
* The second stage inserts new SSA variables at control flow joins.
|
||||
* The last stage replaces references to variables that are assigned to somewhere in the
|
||||
* code by their current SSA variable.
|
||||
*
|
||||
* TODO Which transforms are required to keep this idempotent?
|
||||
*
|
||||
* Prerequisite: Disambiguator.
|
||||
*/
|
||||
class SSATransform: public ASTModifier
|
||||
{
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <libyul/optimiser/ExpressionInliner.h>
|
||||
#include <libyul/optimiser/FullInliner.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||
#include <libyul/optimiser/Rematerialiser.h>
|
||||
#include <libyul/optimiser/UnusedPruner.h>
|
||||
@ -127,12 +128,14 @@ void OptimiserSuite::run(
|
||||
|
||||
{
|
||||
// still in SSA, perform structural simplification
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
ForLoopConditionOutOfBody{_dialect}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
StructuralSimplifier{}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
BlockFlattener{}(ast);
|
||||
DeadCodeEliminator{_dialect}(ast);
|
||||
ForLoopConditionIntoBody{_dialect}(ast);
|
||||
UnusedPruner::runUntilStabilisedOnFullAST(_dialect, ast, reservedIdentifiers);
|
||||
}
|
||||
|
||||
@ -187,6 +190,7 @@ void OptimiserSuite::run(
|
||||
LoadResolver::run(_dialect, ast);
|
||||
ExpressionSimplifier::run(_dialect, ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
ForLoopConditionOutOfBody{_dialect}(ast);
|
||||
StructuralSimplifier{}(ast);
|
||||
BlockFlattener{}(ast);
|
||||
DeadCodeEliminator{_dialect}(ast);
|
||||
@ -195,6 +199,7 @@ void OptimiserSuite::run(
|
||||
SSATransform::run(ast, dispenser);
|
||||
RedundantAssignEliminator::run(_dialect, ast);
|
||||
RedundantAssignEliminator::run(_dialect, ast);
|
||||
ForLoopConditionIntoBody{_dialect}(ast);
|
||||
UnusedPruner::runUntilStabilisedOnFullAST(_dialect, ast, reservedIdentifiers);
|
||||
CommonSubexpressionEliminator::run(_dialect, ast);
|
||||
}
|
||||
@ -212,6 +217,9 @@ void OptimiserSuite::run(
|
||||
|
||||
SSAReverser::run(ast);
|
||||
CommonSubexpressionEliminator::run(_dialect, ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
ForLoopConditionOutOfBody{_dialect}(ast);
|
||||
CommonSubexpressionEliminator::run(_dialect, ast);
|
||||
UnusedPruner::runUntilStabilisedOnFullAST(_dialect, ast, reservedIdentifiers);
|
||||
|
||||
ExpressionJoiner::run(ast);
|
||||
@ -232,6 +240,9 @@ void OptimiserSuite::run(
|
||||
BlockFlattener{}(ast);
|
||||
DeadCodeEliminator{_dialect}(ast);
|
||||
ControlFlowSimplifier{_dialect}(ast);
|
||||
LiteralRematerialiser{_dialect}(ast);
|
||||
ForLoopConditionOutOfBody{_dialect}(ast);
|
||||
CommonSubexpressionEliminator::run(_dialect, ast);
|
||||
|
||||
FunctionGrouper{}(ast);
|
||||
|
||||
|
@ -26,9 +26,9 @@
|
||||
(param $x4 i64)
|
||||
(result i64)
|
||||
(local $v i64)
|
||||
(if (i64.ne (i64.const 0) (i64.or (i64.or (get_local $x1) (get_local $x2)) (get_local $x3))) (then
|
||||
(if (i64.ne (get_local $v) (i64.or (i64.or (get_local $x1) (get_local $x2)) (get_local $x3))) (then
|
||||
(unreachable)))
|
||||
(if (i64.ne (i64.const 0) (i64.shr_u (get_local $x4) (i64.const 32))) (then
|
||||
(if (i64.ne (get_local $v) (i64.shr_u (get_local $x4) (i64.const 32))) (then
|
||||
(unreachable)))
|
||||
(set_local $v (get_local $x4))
|
||||
(get_local $v)
|
||||
@ -107,9 +107,9 @@
|
||||
(param $x4 i64)
|
||||
(result i64)
|
||||
(local $v i64)
|
||||
(if (i64.ne (i64.const 0) (i64.or (i64.or (get_local $x1) (get_local $x2)) (get_local $x3))) (then
|
||||
(if (i64.ne (get_local $v) (i64.or (i64.or (get_local $x1) (get_local $x2)) (get_local $x3))) (then
|
||||
(unreachable)))
|
||||
(if (i64.ne (i64.const 0) (i64.shr_u (get_local $x4) (i64.const 32))) (then
|
||||
(if (i64.ne (get_local $v) (i64.shr_u (get_local $x4) (i64.const 32))) (then
|
||||
(unreachable)))
|
||||
(set_local $v (get_local $x4))
|
||||
(get_local $v)
|
||||
|
@ -836,6 +836,20 @@ BOOST_AUTO_TEST_CASE(shift_constantinople_warning)
|
||||
CHECK_PARSE_WARNING("{ pop(sar(10, 32)) }", TypeError, "The \"sar\" instruction is only available for Constantinople-compatible VMs");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(chainid_instanbul_warning)
|
||||
{
|
||||
if (dev::test::Options::get().evmVersion().hasChainID())
|
||||
return;
|
||||
CHECK_PARSE_WARNING("{ pop(chainid()) }", TypeError, "The \"chainid\" instruction is only available for Istanbul-compatible VMs");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(selfbalance_instanbul_warning)
|
||||
{
|
||||
if (dev::test::Options::get().evmVersion().hasSelfBalance())
|
||||
return;
|
||||
CHECK_PARSE_WARNING("{ pop(selfbalance()) }", TypeError, "The \"selfbalance\" instruction is only available for Istanbul-compatible VMs");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(jump_warning)
|
||||
{
|
||||
CHECK_PARSE_WARNING("{ 1 jump }", Warning, "Jump instructions");
|
||||
|
@ -17,9 +17,9 @@ contract C {
|
||||
// optimize-yul: true
|
||||
// ----
|
||||
// creation:
|
||||
// codeDepositCost: 624400
|
||||
// executionCost: 657
|
||||
// totalCost: 625057
|
||||
// codeDepositCost: 608600
|
||||
// executionCost: 645
|
||||
// totalCost: 609245
|
||||
// external:
|
||||
// a(): 429
|
||||
// b(uint256): 884
|
||||
|
15
test/libsolidity/syntaxTests/inlineAssembly/istanbul.sol
Normal file
15
test/libsolidity/syntaxTests/inlineAssembly/istanbul.sol
Normal file
@ -0,0 +1,15 @@
|
||||
contract C {
|
||||
function f() pure external {
|
||||
assembly {
|
||||
pop(chainid())
|
||||
}
|
||||
}
|
||||
function g() view external {
|
||||
assembly {
|
||||
pop(selfbalance())
|
||||
}
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// EVMVersion: >=istanbul
|
||||
// ----
|
@ -36,6 +36,7 @@
|
||||
#include <libyul/optimiser/ExpressionInliner.h>
|
||||
#include <libyul/optimiser/FullInliner.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||
#include <libyul/optimiser/LoadResolver.h>
|
||||
#include <libyul/optimiser/MainFunction.h>
|
||||
|
@ -0,0 +1,13 @@
|
||||
{
|
||||
for {} div(create(0, 1, 0), shl(msize(), 1)) {}
|
||||
{
|
||||
}
|
||||
}
|
||||
// ====
|
||||
// step: expressionSimplifier
|
||||
// EVMVersion: >byzantium
|
||||
// ----
|
||||
// {
|
||||
// for { } div(create(0, 1, 0), shl(msize(), 1)) { }
|
||||
// { }
|
||||
// }
|
@ -465,21 +465,19 @@
|
||||
// let _1 := 0
|
||||
// let _2 := mload(_1)
|
||||
// let pos := 0x20
|
||||
// let pos_1 := pos
|
||||
// let length := mload(_2)
|
||||
// mstore(pos, length)
|
||||
// pos := 64
|
||||
// let srcPtr := add(_2, pos_1)
|
||||
// let srcPtr := add(_2, 0x20)
|
||||
// let i := _1
|
||||
// for { } 1 { i := add(i, 1) }
|
||||
// for { } lt(i, length) { i := add(i, 1) }
|
||||
// {
|
||||
// if iszero(lt(i, length)) { break }
|
||||
// abi_encode_t_array$_t_contract$_C_$55_$3_memory_to_t_array$_t_address_$3_memory_ptr(mload(srcPtr), pos)
|
||||
// srcPtr := add(srcPtr, pos_1)
|
||||
// srcPtr := add(srcPtr, 0x20)
|
||||
// pos := add(pos, 0x60)
|
||||
// }
|
||||
// let _3 := mload(64)
|
||||
// let _4 := mload(pos_1)
|
||||
// let _4 := mload(0x20)
|
||||
// if slt(sub(_3, _4), 128) { revert(_1, _1) }
|
||||
// let offset := calldataload(add(_4, 64))
|
||||
// let _5 := 0xffffffffffffffff
|
||||
@ -488,7 +486,7 @@
|
||||
// let offset_1 := calldataload(add(_4, 96))
|
||||
// if gt(offset_1, _5) { revert(_1, _1) }
|
||||
// let value3 := abi_decode_t_array$_t_array$_t_uint256_$2_memory_$dyn_memory_ptr(add(_4, offset_1), _3)
|
||||
// sstore(calldataload(_4), calldataload(add(_4, pos_1)))
|
||||
// sstore(calldataload(_4), calldataload(add(_4, 0x20)))
|
||||
// sstore(value2, value3)
|
||||
// sstore(_1, pos)
|
||||
// }
|
||||
@ -504,9 +502,8 @@
|
||||
// let src := add(offset, _1)
|
||||
// if gt(add(add(offset, mul(length, 0x40)), _1), end) { revert(0, 0) }
|
||||
// let i := 0
|
||||
// for { } 1 { i := add(i, 1) }
|
||||
// for { } lt(i, length) { i := add(i, 1) }
|
||||
// {
|
||||
// if iszero(lt(i, length)) { break }
|
||||
// if iszero(slt(add(src, 0x1f), end)) { revert(0, 0) }
|
||||
// let dst_1 := allocateMemory(array_allocation_size_t_array$_t_uint256_$2_memory(0x2))
|
||||
// let dst_2 := dst_1
|
||||
@ -514,9 +511,8 @@
|
||||
// let _2 := add(src, 0x40)
|
||||
// if gt(_2, end) { revert(0, 0) }
|
||||
// let i_1 := 0
|
||||
// for { } 1 { i_1 := add(i_1, 1) }
|
||||
// for { } lt(i_1, 0x2) { i_1 := add(i_1, 1) }
|
||||
// {
|
||||
// if iszero(lt(i_1, 0x2)) { break }
|
||||
// mstore(dst_1, calldataload(src_1))
|
||||
// dst_1 := add(dst_1, _1)
|
||||
// src_1 := add(src_1, _1)
|
||||
@ -538,9 +534,8 @@
|
||||
// let src := add(offset, _1)
|
||||
// if gt(add(add(offset, mul(length, _1)), _1), end) { revert(0, 0) }
|
||||
// let i := 0
|
||||
// for { } 1 { i := add(i, 1) }
|
||||
// for { } lt(i, length) { i := add(i, 1) }
|
||||
// {
|
||||
// if iszero(lt(i, length)) { break }
|
||||
// mstore(dst, calldataload(src))
|
||||
// dst := add(dst, _1)
|
||||
// src := add(src, _1)
|
||||
@ -550,9 +545,8 @@
|
||||
// {
|
||||
// let srcPtr := value
|
||||
// let i := 0
|
||||
// for { } 1 { i := add(i, 1) }
|
||||
// for { } lt(i, 0x3) { i := add(i, 1) }
|
||||
// {
|
||||
// if iszero(lt(i, 0x3)) { break }
|
||||
// mstore(pos, and(mload(srcPtr), sub(shl(160, 1), 1)))
|
||||
// srcPtr := add(srcPtr, 0x20)
|
||||
// pos := add(pos, 0x20)
|
||||
@ -567,12 +561,12 @@
|
||||
// }
|
||||
// function array_allocation_size_t_array$_t_address_$dyn_memory(length) -> size
|
||||
// {
|
||||
// if gt(length, 0xffffffffffffffff) { revert(0, 0) }
|
||||
// if gt(length, 0xffffffffffffffff) { revert(size, size) }
|
||||
// size := add(mul(length, 0x20), 0x20)
|
||||
// }
|
||||
// function array_allocation_size_t_array$_t_uint256_$2_memory(length) -> size
|
||||
// {
|
||||
// if gt(length, 0xffffffffffffffff) { revert(0, 0) }
|
||||
// if gt(length, 0xffffffffffffffff) { revert(size, size) }
|
||||
// size := mul(length, 0x20)
|
||||
// }
|
||||
// }
|
||||
|
@ -233,13 +233,14 @@
|
||||
// ----
|
||||
// {
|
||||
// {
|
||||
// mstore(0x80, 7673901602397024137095011250362199966051872585513276903826533215767972925880)
|
||||
// let _1 := 0x80
|
||||
// mstore(_1, 7673901602397024137095011250362199966051872585513276903826533215767972925880)
|
||||
// mstore(0xa0, 8489654445897228341090914135473290831551238522473825886865492707826370766375)
|
||||
// let notes := add(0x04, calldataload(0x04))
|
||||
// let m := calldataload(0x24)
|
||||
// let n := calldataload(notes)
|
||||
// let _1 := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||
// let challenge := mod(calldataload(0x44), _1)
|
||||
// let _2 := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001
|
||||
// let challenge := mod(calldataload(0x44), _2)
|
||||
// if gt(m, n)
|
||||
// {
|
||||
// mstore(0x00, 404)
|
||||
@ -249,77 +250,75 @@
|
||||
// mstore(0x2a0, caller())
|
||||
// mstore(0x2c0, kn)
|
||||
// mstore(0x2e0, m)
|
||||
// kn := mulmod(sub(_1, kn), challenge, _1)
|
||||
// kn := mulmod(sub(_2, kn), challenge, _2)
|
||||
// hashCommitments(notes, n)
|
||||
// let b := add(0x300, mul(n, 0x80))
|
||||
// let b := add(0x300, mul(n, _1))
|
||||
// let i := 0
|
||||
// let i_1 := i
|
||||
// for { } 1 { i := add(i, 0x01) }
|
||||
// for { } lt(i, n) { i := add(i, 0x01) }
|
||||
// {
|
||||
// if iszero(lt(i, n)) { break }
|
||||
// let _2 := add(calldataload(0x04), mul(i, 0xc0))
|
||||
// let noteIndex := add(_2, 0x24)
|
||||
// let k := i_1
|
||||
// let a := calldataload(add(_2, 0x44))
|
||||
// let _3 := add(calldataload(0x04), mul(i, 0xc0))
|
||||
// let noteIndex := add(_3, 0x24)
|
||||
// let k := 0
|
||||
// let a := calldataload(add(_3, 0x44))
|
||||
// let c := challenge
|
||||
// let _3 := add(i, 0x01)
|
||||
// switch eq(_3, n)
|
||||
// let _4 := add(i, 0x01)
|
||||
// switch eq(_4, n)
|
||||
// case 1 {
|
||||
// k := kn
|
||||
// if eq(m, n) { k := sub(_1, kn) }
|
||||
// if eq(m, n) { k := sub(_2, kn) }
|
||||
// }
|
||||
// case 0 { k := calldataload(noteIndex) }
|
||||
// validateCommitment(noteIndex, k, a)
|
||||
// switch gt(_3, m)
|
||||
// switch gt(_4, m)
|
||||
// case 1 {
|
||||
// kn := addmod(kn, sub(_1, k), _1)
|
||||
// let x := mod(mload(i_1), _1)
|
||||
// k := mulmod(k, x, _1)
|
||||
// a := mulmod(a, x, _1)
|
||||
// c := mulmod(challenge, x, _1)
|
||||
// mstore(i_1, keccak256(i_1, 0x20))
|
||||
// kn := addmod(kn, sub(_2, k), _2)
|
||||
// let x := mod(mload(0), _2)
|
||||
// k := mulmod(k, x, _2)
|
||||
// a := mulmod(a, x, _2)
|
||||
// c := mulmod(challenge, x, _2)
|
||||
// mstore(0, keccak256(0, 0x20))
|
||||
// }
|
||||
// case 0 { kn := addmod(kn, k, _1) }
|
||||
// let _4 := 0x40
|
||||
// calldatacopy(0xe0, add(_2, 164), _4)
|
||||
// calldatacopy(0x20, add(_2, 100), _4)
|
||||
// mstore(0x120, sub(_1, c))
|
||||
// case 0 { kn := addmod(kn, k, _2) }
|
||||
// let _5 := 0x40
|
||||
// calldatacopy(0xe0, add(_3, 164), _5)
|
||||
// calldatacopy(0x20, add(_3, 100), _5)
|
||||
// mstore(0x120, sub(_2, c))
|
||||
// mstore(0x60, k)
|
||||
// mstore(0xc0, a)
|
||||
// let result := call(gas(), 7, i_1, 0xe0, 0x60, 0x1a0, _4)
|
||||
// let result_1 := and(result, call(gas(), 7, i_1, 0x20, 0x60, 0x120, _4))
|
||||
// let result_2 := and(result_1, call(gas(), 7, i_1, 0x80, 0x60, 0x160, _4))
|
||||
// let result_3 := and(result_2, call(gas(), 6, i_1, 0x120, 0x80, 0x160, _4))
|
||||
// result := and(result_3, call(gas(), 6, i_1, 0x160, 0x80, b, _4))
|
||||
// let result := call(gas(), 7, 0, 0xe0, 0x60, 0x1a0, _5)
|
||||
// let result_1 := and(result, call(gas(), 7, 0, 0x20, 0x60, 0x120, _5))
|
||||
// let result_2 := and(result_1, call(gas(), 7, 0, _1, 0x60, 0x160, _5))
|
||||
// let result_3 := and(result_2, call(gas(), 6, 0, 0x120, _1, 0x160, _5))
|
||||
// result := and(result_3, call(gas(), 6, 0, 0x160, _1, b, _5))
|
||||
// if eq(i, m)
|
||||
// {
|
||||
// mstore(0x260, mload(0x20))
|
||||
// mstore(0x280, mload(_4))
|
||||
// mstore(0x280, mload(_5))
|
||||
// mstore(0x1e0, mload(0xe0))
|
||||
// mstore(0x200, sub(0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47, mload(0x100)))
|
||||
// }
|
||||
// if gt(i, m)
|
||||
// {
|
||||
// mstore(0x60, c)
|
||||
// let result_4 := and(result, call(gas(), 7, i_1, 0x20, 0x60, 0x220, _4))
|
||||
// let result_5 := and(result_4, call(gas(), 6, i_1, 0x220, 0x80, 0x260, _4))
|
||||
// result := and(result_5, call(gas(), 6, i_1, 0x1a0, 0x80, 0x1e0, _4))
|
||||
// let result_4 := and(result, call(gas(), 7, 0, 0x20, 0x60, 0x220, _5))
|
||||
// let result_5 := and(result_4, call(gas(), 6, 0, 0x220, _1, 0x260, _5))
|
||||
// result := and(result_5, call(gas(), 6, 0, 0x1a0, _1, 0x1e0, _5))
|
||||
// }
|
||||
// if iszero(result)
|
||||
// {
|
||||
// mstore(i_1, 400)
|
||||
// revert(i_1, 0x20)
|
||||
// mstore(0, 400)
|
||||
// revert(0, 0x20)
|
||||
// }
|
||||
// b := add(b, _4)
|
||||
// b := add(b, _5)
|
||||
// }
|
||||
// if lt(m, n) { validatePairing(0x64) }
|
||||
// if iszero(eq(mod(keccak256(0x2a0, add(b, not(671))), _1), challenge))
|
||||
// if iszero(eq(mod(keccak256(0x2a0, add(b, not(671))), _2), challenge))
|
||||
// {
|
||||
// mstore(i_1, 404)
|
||||
// revert(i_1, 0x20)
|
||||
// mstore(0, 404)
|
||||
// revert(0, 0x20)
|
||||
// }
|
||||
// mstore(i_1, 0x01)
|
||||
// return(i_1, 0x20)
|
||||
// mstore(0, 0x01)
|
||||
// return(0, 0x20)
|
||||
// }
|
||||
// function validatePairing(t2)
|
||||
// {
|
||||
@ -374,9 +373,8 @@
|
||||
// function hashCommitments(notes, n)
|
||||
// {
|
||||
// let i := 0
|
||||
// for { } 1 { i := add(i, 0x01) }
|
||||
// for { } lt(i, n) { i := add(i, 0x01) }
|
||||
// {
|
||||
// if iszero(lt(i, n)) { break }
|
||||
// calldatacopy(add(0x300, mul(i, 0x80)), add(add(notes, mul(i, 0xc0)), 0x60), 0x80)
|
||||
// }
|
||||
// mstore(0, keccak256(0x300, mul(n, 0x80)))
|
||||
|
@ -47,9 +47,9 @@
|
||||
// }
|
||||
// function abi_decode_t_bytes_calldata_ptr(offset, end) -> arrayPos, length
|
||||
// {
|
||||
// if iszero(slt(add(offset, 0x1f), end)) { revert(0, 0) }
|
||||
// if iszero(slt(add(offset, 0x1f), end)) { revert(arrayPos, arrayPos) }
|
||||
// length := calldataload(offset)
|
||||
// if gt(length, 0xffffffffffffffff) { revert(0, 0) }
|
||||
// if gt(length, 0xffffffffffffffff) { revert(arrayPos, arrayPos) }
|
||||
// arrayPos := add(offset, 0x20)
|
||||
// if gt(add(add(offset, length), 0x20), end) { revert(0, 0) }
|
||||
// }
|
||||
|
@ -24,7 +24,7 @@
|
||||
// for { } lt(mload(a), mload(b)) { a := mload(b) }
|
||||
// {
|
||||
// let b_4 := mload(a)
|
||||
// let a_7 := mload(b_4)
|
||||
// b := mload(a_7)
|
||||
// a := mload(b_4)
|
||||
// b := mload(a)
|
||||
// }
|
||||
// }
|
||||
|
@ -16,21 +16,25 @@
|
||||
// {
|
||||
// function copy(from, to) -> length
|
||||
// {
|
||||
// let length_1 := mload(from)
|
||||
// let from_6 := from
|
||||
// let to_7 := to
|
||||
// let length_1 := mload(from_6)
|
||||
// length := length_1
|
||||
// mstore(to, length_1)
|
||||
// let from_2 := add(from, 0x20)
|
||||
// let to_3 := add(to, 0x20)
|
||||
// mstore(to_7, length_1)
|
||||
// let from_2 := add(from_6, 0x20)
|
||||
// let to_3 := add(to_7, 0x20)
|
||||
// let x_4 := 1
|
||||
// let x := x_4
|
||||
// for { }
|
||||
// lt(x, length_1)
|
||||
// {
|
||||
// let x_5 := add(x, 0x20)
|
||||
// let x_9 := x
|
||||
// let x_5 := add(x_9, 0x20)
|
||||
// x := x_5
|
||||
// }
|
||||
// {
|
||||
// mstore(add(to_3, x), mload(add(from_2, x)))
|
||||
// let x_8 := x
|
||||
// mstore(add(to_3, x_8), mload(add(from_2, x_8)))
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
@ -20,7 +20,8 @@
|
||||
// let a_3 := add(a_2, 1)
|
||||
// a := a_3
|
||||
// }
|
||||
// let a_4 := add(a, 1)
|
||||
// let a_5 := a
|
||||
// let a_4 := add(a_5, 1)
|
||||
// a := a_4
|
||||
// mstore(a_4, 1)
|
||||
// }
|
||||
|
@ -12,10 +12,17 @@
|
||||
// {
|
||||
// let a_1 := mload(0)
|
||||
// let a := a_1
|
||||
// for { mstore(0, a_1) } a { mstore(0, a) }
|
||||
// for { mstore(0, a_1) }
|
||||
// a
|
||||
// {
|
||||
// let a_2 := add(a, 3)
|
||||
// let a_4 := a
|
||||
// mstore(0, a_4)
|
||||
// }
|
||||
// {
|
||||
// let a_3 := a
|
||||
// let a_2 := add(a_3, 3)
|
||||
// a := a_2
|
||||
// }
|
||||
// mstore(0, a)
|
||||
// let a_5 := a
|
||||
// mstore(0, a_5)
|
||||
// }
|
||||
|
@ -17,7 +17,14 @@
|
||||
// a := a_2
|
||||
// }
|
||||
// a
|
||||
// { mstore(0, a) }
|
||||
// { mstore(0, a) }
|
||||
// mstore(0, a)
|
||||
// {
|
||||
// let a_4 := a
|
||||
// mstore(0, a_4)
|
||||
// }
|
||||
// {
|
||||
// let a_3 := a
|
||||
// mstore(0, a_3)
|
||||
// }
|
||||
// let a_5 := a
|
||||
// mstore(0, a_5)
|
||||
// }
|
||||
|
@ -15,9 +15,14 @@
|
||||
// for { mstore(0, a_1) }
|
||||
// a
|
||||
// {
|
||||
// let a_2 := add(a, 3)
|
||||
// let a_4 := a
|
||||
// let a_2 := add(a_4, 3)
|
||||
// a := a_2
|
||||
// }
|
||||
// { mstore(0, a) }
|
||||
// mstore(0, a)
|
||||
// {
|
||||
// let a_3 := a
|
||||
// mstore(0, a_3)
|
||||
// }
|
||||
// let a_5 := a
|
||||
// mstore(0, a_5)
|
||||
// }
|
||||
|
@ -26,23 +26,28 @@
|
||||
// let a_3 := add(a_2, 2)
|
||||
// a := a_3
|
||||
// }
|
||||
// let a_9 := a
|
||||
// {
|
||||
// let a_4 := add(a, 4)
|
||||
// let a_4 := add(a_9, 4)
|
||||
// a := a_4
|
||||
// }
|
||||
// let a_10 := a
|
||||
// for {
|
||||
// let a_5 := add(a, 3)
|
||||
// let a_5 := add(a_10, 3)
|
||||
// a := a_5
|
||||
// }
|
||||
// a
|
||||
// {
|
||||
// let a_6 := add(a, 6)
|
||||
// let a_12 := a
|
||||
// let a_6 := add(a_12, 6)
|
||||
// a := a_6
|
||||
// }
|
||||
// {
|
||||
// let a_7 := add(a, 12)
|
||||
// let a_11 := a
|
||||
// let a_7 := add(a_11, 12)
|
||||
// a := a_7
|
||||
// }
|
||||
// let a_8 := add(a, 8)
|
||||
// let a_13 := a
|
||||
// let a_8 := add(a_13, 8)
|
||||
// a := a_8
|
||||
// }
|
||||
|
@ -12,13 +12,15 @@
|
||||
// {
|
||||
// function f(a, b) -> c, d
|
||||
// {
|
||||
// let b_1 := add(b, a)
|
||||
// let b_5 := b
|
||||
// let a_6 := a
|
||||
// let b_1 := add(b_5, a_6)
|
||||
// b := b_1
|
||||
// let c_2 := add(c, b_1)
|
||||
// c := c_2
|
||||
// let d_3 := add(d, c_2)
|
||||
// d := d_3
|
||||
// let a_4 := add(a, d_3)
|
||||
// let a_4 := add(a_6, d_3)
|
||||
// a := a_4
|
||||
// }
|
||||
// }
|
||||
|
@ -28,6 +28,7 @@
|
||||
// let a_6 := 4
|
||||
// a := a_6
|
||||
// }
|
||||
// let a_7 := add(b_4, a)
|
||||
// let a_8 := a
|
||||
// let a_7 := add(b_4, a_8)
|
||||
// a := a_7
|
||||
// }
|
||||
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
let a
|
||||
let b
|
||||
let x
|
||||
if a {
|
||||
if b {
|
||||
x := 2
|
||||
}
|
||||
}
|
||||
// Should create new SSA variables for x here,
|
||||
// but not above because end of block
|
||||
mstore(0, x)
|
||||
}
|
||||
// ====
|
||||
// step: ssaTransform
|
||||
// ----
|
||||
// {
|
||||
// let a
|
||||
// let b
|
||||
// let x_1
|
||||
// let x := x_1
|
||||
// if a
|
||||
// {
|
||||
// if b
|
||||
// {
|
||||
// let x_2 := 2
|
||||
// x := x_2
|
||||
// }
|
||||
// }
|
||||
// let x_3 := x
|
||||
// mstore(0, x_3)
|
||||
// }
|
@ -20,8 +20,10 @@
|
||||
// a := a_2
|
||||
// }
|
||||
// default {
|
||||
// let a_3 := add(a, 8)
|
||||
// let a_4 := a
|
||||
// let a_3 := add(a_4, 8)
|
||||
// a := a_3
|
||||
// }
|
||||
// mstore(0, a)
|
||||
// let a_5 := a
|
||||
// mstore(0, a_5)
|
||||
// }
|
||||
|
@ -0,0 +1,23 @@
|
||||
{
|
||||
let a := mload(0)
|
||||
switch a
|
||||
case 0 { a := add(a, 4) }
|
||||
default { }
|
||||
// should still create an SSA variable for a
|
||||
mstore(0, a)
|
||||
}
|
||||
// ====
|
||||
// step: ssaTransform
|
||||
// ----
|
||||
// {
|
||||
// let a_1 := mload(0)
|
||||
// let a := a_1
|
||||
// switch a_1
|
||||
// case 0 {
|
||||
// let a_2 := add(a_1, 4)
|
||||
// a := a_2
|
||||
// }
|
||||
// default { }
|
||||
// let a_3 := a
|
||||
// mstore(0, a_3)
|
||||
// }
|
@ -33,7 +33,8 @@
|
||||
// a := a_4
|
||||
// mstore(a_4, 0)
|
||||
// }
|
||||
// mstore(a, 0)
|
||||
// let a_6 := a
|
||||
// mstore(a_6, 0)
|
||||
// let a_5 := 4
|
||||
// a := a_5
|
||||
// mstore(a_5, 0)
|
||||
|
@ -28,6 +28,15 @@ using namespace std;
|
||||
using namespace dev;
|
||||
using namespace dev::eth;
|
||||
|
||||
static vector<string> s_evmVersions = {
|
||||
"homestead",
|
||||
"tangerineWhistle",
|
||||
"spuriousDragon",
|
||||
"byzantium",
|
||||
"constantinople",
|
||||
"petersburg"
|
||||
};
|
||||
|
||||
void FuzzerUtil::runCompiler(string const& _input, bool _quiet)
|
||||
{
|
||||
if (!_quiet)
|
||||
@ -76,6 +85,7 @@ void FuzzerUtil::testCompiler(string const& _input, bool _optimize, bool _quiet)
|
||||
config["settings"]["optimizer"] = Json::objectValue;
|
||||
config["settings"]["optimizer"]["enabled"] = _optimize;
|
||||
config["settings"]["optimizer"]["runs"] = 200;
|
||||
config["settings"]["evmVersion"] = s_evmVersions[_input.size() % s_evmVersions.size()];
|
||||
|
||||
// Enable all SourceUnit-level outputs.
|
||||
config["settings"]["outputSelection"]["*"][""][0] = "*";
|
||||
|
@ -19,27 +19,27 @@ endif()
|
||||
if (OSSFUZZ)
|
||||
add_executable(solc_opt_ossfuzz solc_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
target_link_libraries(solc_opt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(solc_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(solc_noopt_ossfuzz solc_noopt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
target_link_libraries(solc_noopt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(solc_noopt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(const_opt_ossfuzz const_opt_ossfuzz.cpp ../fuzzer_common.cpp)
|
||||
target_link_libraries(const_opt_ossfuzz PRIVATE libsolc evmasm)
|
||||
set_target_properties(const_opt_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(const_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(strictasm_diff_ossfuzz strictasm_diff_ossfuzz.cpp yulFuzzerCommon.cpp)
|
||||
target_link_libraries(strictasm_diff_ossfuzz PRIVATE libsolc evmasm yulInterpreter)
|
||||
set_target_properties(strictasm_diff_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(strictasm_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(strictasm_opt_ossfuzz strictasm_opt_ossfuzz.cpp)
|
||||
target_link_libraries(strictasm_opt_ossfuzz PRIVATE yul)
|
||||
set_target_properties(strictasm_opt_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(strictasm_opt_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(strictasm_assembly_ossfuzz strictasm_assembly_ossfuzz.cpp)
|
||||
target_link_libraries(strictasm_assembly_ossfuzz PRIVATE yul)
|
||||
set_target_properties(strictasm_assembly_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(strictasm_assembly_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(yul_proto_ossfuzz yulProtoFuzzer.cpp protoToYul.cpp yulProto.pb.cc)
|
||||
target_include_directories(yul_proto_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
|
||||
@ -48,7 +48,7 @@ if (OSSFUZZ)
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
)
|
||||
set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(yul_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(yul_proto_diff_ossfuzz yulProto_diff_ossfuzz.cpp yulFuzzerCommon.cpp protoToYul.cpp yulProto.pb.cc)
|
||||
target_include_directories(yul_proto_diff_ossfuzz PRIVATE /usr/include/libprotobuf-mutator)
|
||||
@ -58,7 +58,7 @@ if (OSSFUZZ)
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
)
|
||||
set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(yul_proto_diff_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
|
||||
add_executable(abiv2_proto_ossfuzz
|
||||
../../EVMHost.cpp
|
||||
@ -76,7 +76,7 @@ if (OSSFUZZ)
|
||||
protobuf-mutator.a
|
||||
protobuf.a
|
||||
)
|
||||
set_target_properties(abiv2_proto_ossfuzz PROPERTIES LINK_FLAGS "-fsanitize=fuzzer")
|
||||
set_target_properties(abiv2_proto_ossfuzz PROPERTIES LINK_FLAGS ${LIB_FUZZING_ENGINE})
|
||||
else()
|
||||
add_library(solc_opt_ossfuzz
|
||||
solc_opt_ossfuzz.cpp
|
||||
|
@ -43,6 +43,7 @@
|
||||
#include <libyul/optimiser/ExpressionInliner.h>
|
||||
#include <libyul/optimiser/FullInliner.h>
|
||||
#include <libyul/optimiser/ForLoopConditionIntoBody.h>
|
||||
#include <libyul/optimiser/ForLoopConditionOutOfBody.h>
|
||||
#include <libyul/optimiser/ForLoopInitRewriter.h>
|
||||
#include <libyul/optimiser/MainFunction.h>
|
||||
#include <libyul/optimiser/Rematerialiser.h>
|
||||
@ -134,8 +135,8 @@ public:
|
||||
}
|
||||
cout << "(q)quit/(f)flatten/(c)se/initialize var(d)ecls/(x)plit/(j)oin/(g)rouper/(h)oister/" << endl;
|
||||
cout << " (e)xpr inline/(i)nline/(s)implify/varname c(l)eaner/(u)nusedprune/ss(a) transform/" << endl;
|
||||
cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-init-rewriter/f(O)r-loop-condition-into-body/" << endl;
|
||||
cout << " s(t)ructural simplifier/equi(v)alent function combiner/ssa re(V)erser/? " << endl;
|
||||
cout << " (r)edundant assign elim./re(m)aterializer/f(o)r-loop-init-rewriter/for-loop-condition-(I)nto-body/" << endl;
|
||||
cout << " for-loop-condition-(O)ut-of-body/s(t)ructural simplifier/equi(v)alent function combiner/ssa re(V)erser/" << endl;
|
||||
cout << " co(n)trol flow simplifier/stack com(p)ressor/(D)ead code eliminator/(L)oad resolver/? " << endl;
|
||||
cout.flush();
|
||||
int option = readStandardInputChar();
|
||||
@ -151,6 +152,9 @@ public:
|
||||
ForLoopInitRewriter{}(*m_ast);
|
||||
break;
|
||||
case 'O':
|
||||
ForLoopConditionOutOfBody{m_dialect}(*m_ast);
|
||||
break;
|
||||
case 'I':
|
||||
ForLoopConditionIntoBody{m_dialect}(*m_ast);
|
||||
break;
|
||||
case 'c':
|
||||
|
Loading…
Reference in New Issue
Block a user